Merge branch 'master' of github.com:ethcore/parity into move_hash
This commit is contained in:
commit
974d537849
125
Cargo.lock
generated
125
Cargo.lock
generated
@ -114,14 +114,17 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "bytes"
|
||||||
version = "0.5.2"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "0.3.0"
|
version = "0.4.0-dev"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/carllerche/bytes#6529f6392a9717585b8d67e1db96e6fa0fb6cb1f"
|
||||||
|
dependencies = [
|
||||||
|
"stable-heap 0.1.0 (git+https://github.com/carllerche/stable-heap?rev=3c5cd1ca47)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
@ -156,7 +159,7 @@ version = "0.2.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -275,7 +278,7 @@ dependencies = [
|
|||||||
"ethcore-rpc 1.3.0",
|
"ethcore-rpc 1.3.0",
|
||||||
"ethcore-util 1.3.0",
|
"ethcore-util 1.3.0",
|
||||||
"hyper 0.9.4 (git+https://github.com/ethcore/hyper)",
|
"hyper 0.9.4 (git+https://github.com/ethcore/hyper)",
|
||||||
"jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"jsonrpc-core 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"jsonrpc-http-server 6.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)",
|
"jsonrpc-http-server 6.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -289,7 +292,7 @@ dependencies = [
|
|||||||
"serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -415,7 +418,7 @@ dependencies = [
|
|||||||
"ethjson 0.1.0",
|
"ethjson 0.1.0",
|
||||||
"ethsync 1.3.0",
|
"ethsync 1.3.0",
|
||||||
"json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)",
|
"json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)",
|
||||||
"jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"jsonrpc-core 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"jsonrpc-http-server 6.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)",
|
"jsonrpc-http-server 6.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -435,12 +438,12 @@ dependencies = [
|
|||||||
"ethcore-io 1.3.0",
|
"ethcore-io 1.3.0",
|
||||||
"ethcore-rpc 1.3.0",
|
"ethcore-rpc 1.3.0",
|
||||||
"ethcore-util 1.3.0",
|
"ethcore-util 1.3.0",
|
||||||
"jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"jsonrpc-core 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parity-dapps-signer 0.6.0 (git+https://github.com/ethcore/parity-ui.git)",
|
"parity-dapps-signer 0.6.0 (git+https://github.com/ethcore/parity-ui.git)",
|
||||||
"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_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)",
|
||||||
"ws 0.5.0 (git+https://github.com/ethcore/ws-rs.git?branch=stable)",
|
"ws 0.5.2 (git+https://github.com/ethcore/ws-rs.git?branch=mio-upstream-stable)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -615,7 +618,7 @@ dependencies = [
|
|||||||
"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.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"vecio 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"vecio 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -636,7 +639,7 @@ dependencies = [
|
|||||||
"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.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -683,23 +686,23 @@ source = "git+https://github.com/ethcore/json-ipc-server.git#56b6307130710ebc73c
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"jsonrpc-core 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mio 0.5.1 (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.3 (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)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jsonrpc-core"
|
name = "jsonrpc-core"
|
||||||
version = "2.0.7"
|
version = "2.1.1"
|
||||||
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.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -708,7 +711,7 @@ version = "6.1.0"
|
|||||||
source = "git+https://github.com/ethcore/jsonrpc-http-server.git#4e3f93eb79125e91a46e04d77c25ff8885498b86"
|
source = "git+https://github.com/ethcore/jsonrpc-http-server.git#4e3f93eb79125e91a46e04d77c25ff8885498b86"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hyper 0.9.4 (git+https://github.com/ethcore/hyper)",
|
"hyper 0.9.4 (git+https://github.com/ethcore/hyper)",
|
||||||
"jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"jsonrpc-core 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -781,7 +784,7 @@ dependencies = [
|
|||||||
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (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.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"nix 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nix 0.5.0 (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)",
|
||||||
@ -797,7 +800,7 @@ dependencies = [
|
|||||||
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (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.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"nix 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nix 0.5.0 (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)",
|
||||||
@ -805,9 +808,24 @@ dependencies = [
|
|||||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio"
|
||||||
|
version = "0.6.0-dev"
|
||||||
|
source = "git+https://github.com/carllerche/mio?rev=62ec763c9cc34d8a452ed0392c575c50ddd5fc8d#62ec763c9cc34d8a452ed0392c575c50ddd5fc8d"
|
||||||
|
dependencies = [
|
||||||
|
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"slab 0.2.0 (git+https://github.com/carllerche/slab?rev=5476efcafb)",
|
||||||
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miow"
|
name = "miow"
|
||||||
version = "0.1.2"
|
version = "0.1.3"
|
||||||
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.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -855,6 +873,19 @@ dependencies = [
|
|||||||
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nix"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nodrop"
|
name = "nodrop"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
@ -1256,11 +1287,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha1"
|
name = "sha1"
|
||||||
version = "0.1.1"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
|
||||||
"byteorder 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha3"
|
name = "sha3"
|
||||||
@ -1274,6 +1302,11 @@ name = "slab"
|
|||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slab"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "git+https://github.com/carllerche/slab?rev=5476efcafb#5476efcafbc5ef4d7315b1bea3f756d8a1fe975e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@ -1298,6 +1331,11 @@ name = "spmc"
|
|||||||
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"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stable-heap"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/carllerche/stable-heap?rev=3c5cd1ca47#3c5cd1ca4706f167a1de85658b5af0d6d3e65165"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -1448,7 +1486,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "url"
|
||||||
version = "1.1.1"
|
version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1507,15 +1545,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ws"
|
name = "ws"
|
||||||
version = "0.5.0"
|
version = "0.5.2"
|
||||||
source = "git+https://github.com/ethcore/ws-rs.git?branch=stable#a876fc115c3ef50a17c8822c9bd2f6e94473e005"
|
source = "git+https://github.com/ethcore/ws-rs.git?branch=mio-upstream-stable#afbff59776ce16ccec5ee9e218b8891830ee6fdf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bytes 0.4.0-dev (git+https://github.com/carllerche/bytes)",
|
||||||
"httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)",
|
"mio 0.6.0-dev (git+https://github.com/carllerche/mio?rev=62ec763c9cc34d8a452ed0392c575c50ddd5fc8d)",
|
||||||
"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)",
|
||||||
"sha1 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"slab 0.2.0 (git+https://github.com/carllerche/slab?rev=5476efcafb)",
|
||||||
|
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1550,16 +1590,13 @@ dependencies = [
|
|||||||
"checksum aster 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07d344974f0a155f091948aa389fb1b912d3a58414fbdb9c8d446d193ee3496a"
|
"checksum aster 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07d344974f0a155f091948aa389fb1b912d3a58414fbdb9c8d446d193ee3496a"
|
||||||
"checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
|
"checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
|
||||||
"checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d"
|
"checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d"
|
||||||
"checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c"
|
|
||||||
"checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3"
|
"checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3"
|
||||||
"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
|
"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
|
||||||
"checksum bitflags 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "72cd7314bd4ee024071241147222c706e80385a1605ac7d4cd2fcc339da2ae46"
|
|
||||||
"checksum blastfig 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "09640e0509d97d5cdff03a9f5daf087a8e04c735c3b113a75139634a19cfc7b2"
|
"checksum blastfig 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "09640e0509d97d5cdff03a9f5daf087a8e04c735c3b113a75139634a19cfc7b2"
|
||||||
"checksum bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f421095d2a76fc24cd3fb3f912b90df06be7689912b1bdb423caefae59c258d"
|
"checksum bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f421095d2a76fc24cd3fb3f912b90df06be7689912b1bdb423caefae59c258d"
|
||||||
"checksum byteorder 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e68d0b3b234a583993a53d5b0063fb5fe8713590fe733d41b98a2cee6a9c26e"
|
|
||||||
"checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27"
|
"checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27"
|
||||||
|
"checksum bytes 0.4.0-dev (git+https://github.com/carllerche/bytes)" = "<none>"
|
||||||
"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
|
"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
|
||||||
"checksum chrono 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "a714b6792cb4bb07643c35d2a051d92988d4e296322a60825549dd0764bcd396"
|
|
||||||
"checksum clippy 0.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "e96469b413984c78285727f94f9c626a1f2006cecdcf813b5d6893c0c85df42f"
|
"checksum clippy 0.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "e96469b413984c78285727f94f9c626a1f2006cecdcf813b5d6893c0c85df42f"
|
||||||
"checksum clippy_lints 0.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "f11938c4b10c556903bb1c1e717eb038658324bf7197e4cfc159a16417327345"
|
"checksum clippy_lints 0.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "f11938c4b10c556903bb1c1e717eb038658324bf7197e4cfc159a16417327345"
|
||||||
"checksum cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90266f45846f14a1e986c77d1e9c2626b8c342ed806fe60241ec38cc8697b245"
|
"checksum cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90266f45846f14a1e986c77d1e9c2626b8c342ed806fe60241ec38cc8697b245"
|
||||||
@ -1578,13 +1615,14 @@ dependencies = [
|
|||||||
"checksum hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2da7d3a34cf6406d9d700111b8eafafe9a251de41ae71d8052748259343b58"
|
"checksum hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2da7d3a34cf6406d9d700111b8eafafe9a251de41ae71d8052748259343b58"
|
||||||
"checksum httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46534074dbb80b070d60a5cb8ecadd8963a00a438ae1a95268850a7ef73b67ae"
|
"checksum httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46534074dbb80b070d60a5cb8ecadd8963a00a438ae1a95268850a7ef73b67ae"
|
||||||
"checksum hyper 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bb0f4d00bb781e559b6e66ae4b5479df0fdf9ab15949f52fa2f1f5de16d4cc07"
|
"checksum hyper 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bb0f4d00bb781e559b6e66ae4b5479df0fdf9ab15949f52fa2f1f5de16d4cc07"
|
||||||
|
"checksum hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "eb27e8a3e8f17ac43ffa41bbda9cf5ad3f9f13ef66fa4873409d4902310275f7"
|
||||||
"checksum hyper 0.9.4 (git+https://github.com/ethcore/hyper)" = "<none>"
|
"checksum hyper 0.9.4 (git+https://github.com/ethcore/hyper)" = "<none>"
|
||||||
"checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"
|
"checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"
|
||||||
"checksum igd 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5b93df68d6152576e9bc9f371e33e00b40738d528b3566ff41ea11d04401dc"
|
"checksum igd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c8c12b1795b8b168f577c45fa10379b3814dcb11b7ab702406001f0d63f40484"
|
||||||
"checksum isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7408a548dc0e406b7912d9f84c261cc533c1866e047644a811c133c56041ac0c"
|
"checksum isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7408a548dc0e406b7912d9f84c261cc533c1866e047644a811c133c56041ac0c"
|
||||||
"checksum itertools 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "086e1fa5fe48840b1cfdef3a20c7e3115599f8d5c4c87ef32a794a7cdd184d76"
|
"checksum itertools 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "086e1fa5fe48840b1cfdef3a20c7e3115599f8d5c4c87ef32a794a7cdd184d76"
|
||||||
"checksum json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)" = "<none>"
|
"checksum json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)" = "<none>"
|
||||||
"checksum jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "91755680900913f73576065c85359ee793ac3883bc461dbca90fc4a603be84cc"
|
"checksum jsonrpc-core 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ec4477e4e8218da23caa5dd31f4eb39999aa0ea9035660617eccfb19a23bf5ad"
|
||||||
"checksum jsonrpc-http-server 6.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)" = "<none>"
|
"checksum jsonrpc-http-server 6.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)" = "<none>"
|
||||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||||
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
|
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
|
||||||
@ -1597,11 +1635,13 @@ dependencies = [
|
|||||||
"checksum mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e50bf542f81754ef69e5cea856946a3819f7c09ea97b4903c8bc8a89f74e7b6"
|
"checksum mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e50bf542f81754ef69e5cea856946a3819f7c09ea97b4903c8bc8a89f74e7b6"
|
||||||
"checksum mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)" = "<none>"
|
"checksum mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)" = "<none>"
|
||||||
"checksum mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a637d1ca14eacae06296a008fa7ad955347e34efcb5891cfd8ba05491a37907e"
|
"checksum mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a637d1ca14eacae06296a008fa7ad955347e34efcb5891cfd8ba05491a37907e"
|
||||||
"checksum miow 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4e93d633d34b8ff65a24566d67d49703e7a5c7ac2844d6139a9fc441a799e89a"
|
"checksum mio 0.6.0-dev (git+https://github.com/carllerche/mio?rev=62ec763c9cc34d8a452ed0392c575c50ddd5fc8d)" = "<none>"
|
||||||
|
"checksum miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d5bfc6782530ac8ace97af10a540054a37126b63b0702ddaaa243b73b5745b9a"
|
||||||
"checksum nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)" = "<none>"
|
"checksum nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)" = "<none>"
|
||||||
"checksum nanomsg-sys 0.5.0 (git+https://github.com/ethcore/nanomsg.rs.git)" = "<none>"
|
"checksum nanomsg-sys 0.5.0 (git+https://github.com/ethcore/nanomsg.rs.git)" = "<none>"
|
||||||
"checksum net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "6a816012ca11cb47009693c1e0c6130e26d39e4d97ee2a13c50e868ec83e3204"
|
"checksum net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "6a816012ca11cb47009693c1e0c6130e26d39e4d97ee2a13c50e868ec83e3204"
|
||||||
"checksum nix 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f05c2fc965fc1cd6b73fa57fa7b89f288178737f2f3ce9e63e4a6a141189000e"
|
"checksum nix 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f05c2fc965fc1cd6b73fa57fa7b89f288178737f2f3ce9e63e4a6a141189000e"
|
||||||
|
"checksum nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a7bb1da2be7da3cbffda73fc681d509ffd9e665af478d2bee1907cee0bc64b2"
|
||||||
"checksum nodrop 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4d9a22dbcebdeef7bf275cbf444d6521d4e7a2fee187b72d80dba0817120dd8f"
|
"checksum nodrop 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4d9a22dbcebdeef7bf275cbf444d6521d4e7a2fee187b72d80dba0817120dd8f"
|
||||||
"checksum nom 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6caab12c5f97aa316cb249725aa32115118e1522b445e26c257dd77cad5ffd4e"
|
"checksum nom 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6caab12c5f97aa316cb249725aa32115118e1522b445e26c257dd77cad5ffd4e"
|
||||||
"checksum num 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "c04bd954dbf96f76bab6e5bd6cef6f1ce1262d15268ce4f926d2b5b778fa7af2"
|
"checksum num 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "c04bd954dbf96f76bab6e5bd6cef6f1ce1262d15268ce4f926d2b5b778fa7af2"
|
||||||
@ -1649,12 +1689,14 @@ dependencies = [
|
|||||||
"checksum serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b76133a8a02f1c6ebd3fb9a2ecaab3d54302565a51320e80931adba571aadb1b"
|
"checksum serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b76133a8a02f1c6ebd3fb9a2ecaab3d54302565a51320e80931adba571aadb1b"
|
||||||
"checksum serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c5b74ff4fb34013cc0b917dd182fefc05ee9af233b9d0d557078334554284d0e"
|
"checksum serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c5b74ff4fb34013cc0b917dd182fefc05ee9af233b9d0d557078334554284d0e"
|
||||||
"checksum serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c88a751caa8f0000058fb971cd443ed2e6b653f33f5a47f29892a8bd44ca4c1"
|
"checksum serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c88a751caa8f0000058fb971cd443ed2e6b653f33f5a47f29892a8bd44ca4c1"
|
||||||
"checksum sha1 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a307a40d5834140e4213a6952483b84e9ad53bdcab918b7335a6e305e505a53c"
|
"checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c"
|
||||||
"checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e"
|
"checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e"
|
||||||
|
"checksum slab 0.2.0 (git+https://github.com/carllerche/slab?rev=5476efcafb)" = "<none>"
|
||||||
"checksum slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6dbdd334bd28d328dad1c41b0ea662517883d8880d8533895ef96c8003dec9c4"
|
"checksum slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6dbdd334bd28d328dad1c41b0ea662517883d8880d8533895ef96c8003dec9c4"
|
||||||
"checksum smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fcc8d19212aacecf95e4a7a2179b26f7aeb9732a915cf01f05b0d3e044865410"
|
"checksum smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fcc8d19212aacecf95e4a7a2179b26f7aeb9732a915cf01f05b0d3e044865410"
|
||||||
"checksum solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "172382bac9424588d7840732b250faeeef88942e37b6e35317dce98cafdd75b2"
|
"checksum solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "172382bac9424588d7840732b250faeeef88942e37b6e35317dce98cafdd75b2"
|
||||||
"checksum spmc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93bdab61c1a413e591c4d17388ffa859eaff2df27f1e13a5ec8b716700605adf"
|
"checksum spmc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93bdab61c1a413e591c4d17388ffa859eaff2df27f1e13a5ec8b716700605adf"
|
||||||
|
"checksum stable-heap 0.1.0 (git+https://github.com/carllerche/stable-heap?rev=3c5cd1ca47)" = "<none>"
|
||||||
"checksum strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4d73a2c36a4d095ed1a6df5cbeac159863173447f7a82b3f4757426844ab825"
|
"checksum strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4d73a2c36a4d095ed1a6df5cbeac159863173447f7a82b3f4757426844ab825"
|
||||||
"checksum syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393b6dd0889df2b064beeea954cfda6bc2571604ac460deeae0fed55a53988af"
|
"checksum syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393b6dd0889df2b064beeea954cfda6bc2571604ac460deeae0fed55a53988af"
|
||||||
"checksum syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44bded3cabafc65c90b663b1071bd2d198a9ab7515e6ce729e4570aaf53c407e"
|
"checksum syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44bded3cabafc65c90b663b1071bd2d198a9ab7515e6ce729e4570aaf53c407e"
|
||||||
@ -1674,7 +1716,7 @@ dependencies = [
|
|||||||
"checksum unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26643a2f83bac55f1976fb716c10234485f9202dcd65cfbdf9da49867b271172"
|
"checksum unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26643a2f83bac55f1976fb716c10234485f9202dcd65cfbdf9da49867b271172"
|
||||||
"checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb"
|
"checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb"
|
||||||
"checksum url 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f6d04073d0fcd045a1cf57aea560d1be5ba812d8f28814e1e1cf0e90ff4d2f03"
|
"checksum url 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f6d04073d0fcd045a1cf57aea560d1be5ba812d8f28814e1e1cf0e90ff4d2f03"
|
||||||
"checksum url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8ab4ca6f0107350f41a59a51cb0e71a04d905bc6a29181d2cb42fa4f040c65c9"
|
"checksum url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afe9ec54bc4db14bc8744b7fed060d785ac756791450959b2248443319d5b119"
|
||||||
"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
|
"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
|
||||||
"checksum uuid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9767696a9e1bc7a73f2d5f8e0f5428b076cecd9199c200c0364aa0b2d57b8dfa"
|
"checksum uuid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9767696a9e1bc7a73f2d5f8e0f5428b076cecd9199c200c0364aa0b2d57b8dfa"
|
||||||
"checksum vecio 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0795a11576d29ae80525a3fda315bf7b534f8feb9d34101e5fe63fb95bb2fd24"
|
"checksum vecio 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0795a11576d29ae80525a3fda315bf7b534f8feb9d34101e5fe63fb95bb2fd24"
|
||||||
@ -1682,8 +1724,7 @@ dependencies = [
|
|||||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||||
"checksum winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4dfaaa8fbdaa618fa6914b59b2769d690dd7521920a18d84b42d254678dd5fd4"
|
"checksum winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4dfaaa8fbdaa618fa6914b59b2769d690dd7521920a18d84b42d254678dd5fd4"
|
||||||
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||||
"checksum ws 0.5.0 (git+https://github.com/ethcore/ws-rs.git?branch=stable)" = "<none>"
|
"checksum ws 0.5.2 (git+https://github.com/ethcore/ws-rs.git?branch=mio-upstream-stable)" = "<none>"
|
||||||
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
|
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
|
||||||
"checksum xml-rs 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "4bac8fd82b24db2dd3b54aa7b29f336d8b5ca1830065ce3aada71bce6f661519"
|
"checksum xml-rs 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "65e74b96bd3179209dc70a980da6df843dff09e46eee103a0376c0949257e3ef"
|
||||||
"checksum xml-rs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f11ef7864e55d06a38755beaf03ab70139a04e619acfe94ef800b11bd79eb52c"
|
|
||||||
"checksum xmltree 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "472a9d37c7c53ab2391161df5b89b1f3bf76dab6ab150d7941ecbdd832282082"
|
"checksum xmltree 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "472a9d37c7c53ab2391161df5b89b1f3bf76dab6ab150d7941ecbdd832282082"
|
||||||
|
@ -10,7 +10,7 @@ build = "build.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
jsonrpc-core = "2.0"
|
jsonrpc-core = "2.1"
|
||||||
jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc-http-server.git" }
|
jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc-http-server.git" }
|
||||||
hyper = { default-features = false, git = "https://github.com/ethcore/hyper" }
|
hyper = { default-features = false, git = "https://github.com/ethcore/hyper" }
|
||||||
unicase = "1.3"
|
unicase = "1.3"
|
||||||
|
@ -775,12 +775,20 @@ impl BlockChain {
|
|||||||
|
|
||||||
/// Applt pending insertion updates
|
/// Applt pending insertion updates
|
||||||
pub fn commit(&self) {
|
pub fn commit(&self) {
|
||||||
let mut best_block = self.best_block.write();
|
|
||||||
let mut write_hashes = self.block_hashes.write();
|
|
||||||
let mut write_txs = self.transaction_addresses.write();
|
|
||||||
let mut pending_best_block = self.pending_best_block.write();
|
let mut pending_best_block = self.pending_best_block.write();
|
||||||
let mut pending_write_hashes = self.pending_block_hashes.write();
|
let mut pending_write_hashes = self.pending_block_hashes.write();
|
||||||
let mut pending_write_txs = self.pending_transaction_addresses.write();
|
let mut pending_write_txs = self.pending_transaction_addresses.write();
|
||||||
|
|
||||||
|
for n in pending_write_hashes.keys() {
|
||||||
|
self.note_used(CacheID::BlockHashes(*n));
|
||||||
|
}
|
||||||
|
for hash in pending_write_txs.keys() {
|
||||||
|
self.note_used(CacheID::TransactionAddresses(hash.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut best_block = self.best_block.write();
|
||||||
|
let mut write_hashes = self.block_hashes.write();
|
||||||
|
let mut write_txs = self.transaction_addresses.write();
|
||||||
// update best block
|
// update best block
|
||||||
if let Some(block) = pending_best_block.take() {
|
if let Some(block) = pending_best_block.take() {
|
||||||
*best_block = block;
|
*best_block = block;
|
||||||
|
@ -594,19 +594,35 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Take a snapshot.
|
/// Take a snapshot at the given block.
|
||||||
pub fn take_snapshot<W: snapshot_io::SnapshotWriter + Send>(&self, writer: W) -> Result<(), ::error::Error> {
|
/// If the ID given is "latest", this will default to 1000 blocks behind.
|
||||||
|
pub fn take_snapshot<W: snapshot_io::SnapshotWriter + Send>(&self, writer: W, at: BlockID, p: &snapshot::Progress) -> Result<(), ::error::Error> {
|
||||||
let db = self.state_db.lock().boxed_clone();
|
let db = self.state_db.lock().boxed_clone();
|
||||||
let best_block_number = self.chain_info().best_block_number;
|
let best_block_number = self.chain_info().best_block_number;
|
||||||
let start_block_number = if best_block_number > 1000 {
|
let block_number = try!(self.block_number(at).ok_or(snapshot::Error::InvalidStartingBlock(at)));
|
||||||
|
|
||||||
|
if best_block_number > HISTORY + block_number && db.is_pruned() {
|
||||||
|
return Err(snapshot::Error::OldBlockPrunedDB.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let start_hash = match at {
|
||||||
|
BlockID::Latest => {
|
||||||
|
let start_num = if best_block_number > 1000 {
|
||||||
best_block_number - 1000
|
best_block_number - 1000
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
let start_hash = self.block_hash(BlockID::Number(start_block_number))
|
|
||||||
.expect("blocks within HISTORY are always stored.");
|
|
||||||
|
|
||||||
try!(snapshot::take_snapshot(&self.chain, start_hash, db.as_hashdb(), writer));
|
self.block_hash(BlockID::Number(start_num))
|
||||||
|
.expect("blocks within HISTORY are always stored.")
|
||||||
|
}
|
||||||
|
_ => match self.block_hash(at) {
|
||||||
|
Some(hash) => hash,
|
||||||
|
None => return Err(snapshot::Error::InvalidStartingBlock(at).into()),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
try!(snapshot::take_snapshot(&self.chain, start_hash, db.as_hashdb(), writer, p));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -784,8 +800,8 @@ impl BlockChainClient for Client {
|
|||||||
Self::block_hash(&self.chain, id)
|
Self::block_hash(&self.chain, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn code(&self, address: &Address) -> Option<Bytes> {
|
fn code(&self, address: &Address, id: BlockID) -> Option<Option<Bytes>> {
|
||||||
self.state().code(address)
|
self.state_at(id).map(|s| s.code(address))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn balance(&self, address: &Address, id: BlockID) -> Option<U256> {
|
fn balance(&self, address: &Address, id: BlockID) -> Option<U256> {
|
||||||
|
@ -319,8 +319,11 @@ impl BlockChainClient for TestBlockChainClient {
|
|||||||
self.nonce(address, BlockID::Latest).unwrap()
|
self.nonce(address, BlockID::Latest).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn code(&self, address: &Address) -> Option<Bytes> {
|
fn code(&self, address: &Address, id: BlockID) -> Option<Option<Bytes>> {
|
||||||
self.code.read().get(address).cloned()
|
match id {
|
||||||
|
BlockID::Latest => Some(self.code.read().get(address).cloned()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn balance(&self, address: &Address, id: BlockID) -> Option<U256> {
|
fn balance(&self, address: &Address, id: BlockID) -> Option<U256> {
|
||||||
|
@ -78,8 +78,14 @@ pub trait BlockChainClient : Sync + Send {
|
|||||||
/// Get block hash.
|
/// Get block hash.
|
||||||
fn block_hash(&self, id: BlockID) -> Option<H256>;
|
fn block_hash(&self, id: BlockID) -> Option<H256>;
|
||||||
|
|
||||||
/// Get address code.
|
/// Get address code at given block's state.
|
||||||
fn code(&self, address: &Address) -> Option<Bytes>;
|
fn code(&self, address: &Address, id: BlockID) -> Option<Option<Bytes>>;
|
||||||
|
|
||||||
|
/// Get address code at the latest block's state.
|
||||||
|
fn latest_code(&self, address: &Address) -> Option<Bytes> {
|
||||||
|
self.code(address, BlockID::Latest)
|
||||||
|
.expect("code will return Some if given BlockID::Latest; qed")
|
||||||
|
}
|
||||||
|
|
||||||
/// Get address balance at the given block's state.
|
/// Get address balance at the given block's state.
|
||||||
///
|
///
|
||||||
|
@ -151,10 +151,14 @@ impl CostType for usize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_u256(val: U256) -> Result<Self> {
|
fn from_u256(val: U256) -> Result<Self> {
|
||||||
if U256::from(val.low_u64()) != val {
|
let res = val.low_u64() as usize;
|
||||||
|
|
||||||
|
// validate if value fits into usize
|
||||||
|
if U256::from(res) != val {
|
||||||
return Err(Error::OutOfGas);
|
return Err(Error::OutOfGas);
|
||||||
}
|
}
|
||||||
Ok(val.low_u64() as usize)
|
|
||||||
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_usize(&self) -> usize {
|
fn as_usize(&self) -> usize {
|
||||||
@ -191,6 +195,7 @@ pub trait Evm {
|
|||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(test)]
|
||||||
fn should_calculate_overflow_mul_shr_without_overflow() {
|
fn should_calculate_overflow_mul_shr_without_overflow() {
|
||||||
// given
|
// given
|
||||||
let num = 1048576;
|
let num = 1048576;
|
||||||
@ -207,6 +212,7 @@ fn should_calculate_overflow_mul_shr_without_overflow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(test)]
|
||||||
fn should_calculate_overflow_mul_shr_with_overflow() {
|
fn should_calculate_overflow_mul_shr_with_overflow() {
|
||||||
// given
|
// given
|
||||||
let max = ::std::u64::MAX;
|
let max = ::std::u64::MAX;
|
||||||
@ -225,3 +231,15 @@ fn should_calculate_overflow_mul_shr_with_overflow() {
|
|||||||
assert!(o1);
|
assert!(o1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(test)]
|
||||||
|
fn should_validate_u256_to_usize_conversion() {
|
||||||
|
// given
|
||||||
|
let v = U256::from(::std::usize::MAX) + U256::from(1);
|
||||||
|
|
||||||
|
// when
|
||||||
|
let res = usize::from_u256(v);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assert!(res.is_err());
|
||||||
|
}
|
||||||
|
@ -515,11 +515,11 @@ impl<Cost: CostType> Interpreter<Cost> {
|
|||||||
Ok(InstructionResult::Ok)
|
Ok(InstructionResult::Ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_data_to_memory(&mut self, stack: &mut Stack<U256>, data: &[u8]) {
|
fn copy_data_to_memory(&mut self, stack: &mut Stack<U256>, source: &[u8]) {
|
||||||
let dest_offset = stack.pop_back();
|
let dest_offset = stack.pop_back();
|
||||||
let source_offset = stack.pop_back();
|
let source_offset = stack.pop_back();
|
||||||
let size = stack.pop_back();
|
let size = stack.pop_back();
|
||||||
let source_size = U256::from(data.len());
|
let source_size = U256::from(source.len());
|
||||||
|
|
||||||
let output_end = match source_offset > source_size || size > source_size || source_offset + size > source_size {
|
let output_end = match source_offset > source_size || size > source_size || source_offset + size > source_size {
|
||||||
true => {
|
true => {
|
||||||
@ -531,14 +531,14 @@ impl<Cost: CostType> Interpreter<Cost> {
|
|||||||
for i in zero_slice.iter_mut() {
|
for i in zero_slice.iter_mut() {
|
||||||
*i = 0;
|
*i = 0;
|
||||||
}
|
}
|
||||||
data.len()
|
source.len()
|
||||||
},
|
},
|
||||||
false => (size.low_u64() + source_offset.low_u64()) as usize
|
false => (size.low_u64() + source_offset.low_u64()) as usize
|
||||||
};
|
};
|
||||||
|
|
||||||
if source_offset < source_size {
|
if source_offset < source_size {
|
||||||
let output_begin = source_offset.low_u64() as usize;
|
let output_begin = source_offset.low_u64() as usize;
|
||||||
self.mem.write_slice(dest_offset, &data[output_begin..output_end]);
|
self.mem.write_slice(dest_offset, &source[output_begin..output_end]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -528,7 +528,7 @@ impl MinerService for Miner {
|
|||||||
|
|
||||||
fn code(&self, chain: &MiningBlockChainClient, address: &Address) -> Option<Bytes> {
|
fn code(&self, chain: &MiningBlockChainClient, address: &Address) -> Option<Bytes> {
|
||||||
let sealing_work = self.sealing_work.lock();
|
let sealing_work = self.sealing_work.lock();
|
||||||
sealing_work.queue.peek_last_ref().map_or_else(|| chain.code(address), |b| b.block().fields().state.code(address))
|
sealing_work.queue.peek_last_ref().map_or_else(|| chain.latest_code(address), |b| b.block().fields().state.code(address))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_author(&self, author: Address) {
|
fn set_author(&self, author: Address) {
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
use ids::BlockID;
|
||||||
|
|
||||||
use util::H256;
|
use util::H256;
|
||||||
use util::trie::TrieError;
|
use util::trie::TrieError;
|
||||||
use util::rlp::DecoderError;
|
use util::rlp::DecoderError;
|
||||||
@ -26,9 +28,13 @@ use util::rlp::DecoderError;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Invalid starting block for snapshot.
|
/// Invalid starting block for snapshot.
|
||||||
InvalidStartingBlock(H256),
|
InvalidStartingBlock(BlockID),
|
||||||
/// Block not found.
|
/// Block not found.
|
||||||
BlockNotFound(H256),
|
BlockNotFound(H256),
|
||||||
|
/// Incomplete chain.
|
||||||
|
IncompleteChain,
|
||||||
|
/// Old starting block in a pruned database.
|
||||||
|
OldBlockPrunedDB,
|
||||||
/// Trie error.
|
/// Trie error.
|
||||||
Trie(TrieError),
|
Trie(TrieError),
|
||||||
/// Decoder error.
|
/// Decoder error.
|
||||||
@ -40,8 +46,11 @@ pub enum Error {
|
|||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
Error::InvalidStartingBlock(ref hash) => write!(f, "Invalid starting block hash: {}", hash),
|
Error::InvalidStartingBlock(ref id) => write!(f, "Invalid starting block: {:?}", id),
|
||||||
Error::BlockNotFound(ref hash) => write!(f, "Block not found in chain: {}", hash),
|
Error::BlockNotFound(ref hash) => write!(f, "Block not found in chain: {}", hash),
|
||||||
|
Error::IncompleteChain => write!(f, "Cannot create snapshot due to incomplete chain."),
|
||||||
|
Error::OldBlockPrunedDB => write!(f, "Attempted to create a snapshot at an old block while using \
|
||||||
|
a pruned database. Please re-run with the --pruning archive flag."),
|
||||||
Error::Io(ref err) => err.fmt(f),
|
Error::Io(ref err) => err.fmt(f),
|
||||||
Error::Decoder(ref err) => err.fmt(f),
|
Error::Decoder(ref err) => err.fmt(f),
|
||||||
Error::Trie(ref err) => err.fmt(f),
|
Error::Trie(ref err) => err.fmt(f),
|
||||||
|
@ -18,10 +18,12 @@
|
|||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||||
|
|
||||||
use account_db::{AccountDB, AccountDBMut};
|
use account_db::{AccountDB, AccountDBMut};
|
||||||
use blockchain::{BlockChain, BlockProvider};
|
use blockchain::{BlockChain, BlockProvider};
|
||||||
use engines::Engine;
|
use engines::Engine;
|
||||||
|
use ids::BlockID;
|
||||||
use views::BlockView;
|
use views::BlockView;
|
||||||
|
|
||||||
use util::{Bytes, Hashable, HashDB, snappy, TrieDB, TrieDBMut, TrieMut};
|
use util::{Bytes, Hashable, HashDB, snappy, TrieDB, TrieDBMut, TrieMut};
|
||||||
@ -58,9 +60,49 @@ const PREFERRED_CHUNK_SIZE: usize = 4 * 1024 * 1024;
|
|||||||
// How many blocks to include in a snapshot, starting from the head of the chain.
|
// How many blocks to include in a snapshot, starting from the head of the chain.
|
||||||
const SNAPSHOT_BLOCKS: u64 = 30000;
|
const SNAPSHOT_BLOCKS: u64 = 30000;
|
||||||
|
|
||||||
|
/// A progress indicator for snapshots.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Progress {
|
||||||
|
accounts: AtomicUsize,
|
||||||
|
blocks: AtomicUsize,
|
||||||
|
size: AtomicUsize, // Todo [rob] use Atomicu64 when it stabilizes.
|
||||||
|
done: AtomicBool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Progress {
|
||||||
|
/// Create a new progress indicator.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Progress {
|
||||||
|
accounts: AtomicUsize::new(0),
|
||||||
|
blocks: AtomicUsize::new(0),
|
||||||
|
size: AtomicUsize::new(0),
|
||||||
|
done: AtomicBool::new(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the number of accounts snapshotted thus far.
|
||||||
|
pub fn accounts(&self) -> usize { self.accounts.load(Ordering::Relaxed) }
|
||||||
|
|
||||||
|
/// Get the number of blocks snapshotted thus far.
|
||||||
|
pub fn blocks(&self) -> usize { self.blocks.load(Ordering::Relaxed) }
|
||||||
|
|
||||||
|
/// Get the written size of the snapshot in bytes.
|
||||||
|
pub fn size(&self) -> usize { self.size.load(Ordering::Relaxed) }
|
||||||
|
|
||||||
|
/// Whether the snapshot is complete.
|
||||||
|
pub fn done(&self) -> bool { self.done.load(Ordering::SeqCst) }
|
||||||
|
|
||||||
|
}
|
||||||
/// Take a snapshot using the given blockchain, starting block hash, and database, writing into the given writer.
|
/// Take a snapshot using the given blockchain, starting block hash, and database, writing into the given writer.
|
||||||
pub fn take_snapshot<W: SnapshotWriter + Send>(chain: &BlockChain, start_block_hash: H256, state_db: &HashDB, writer: W) -> Result<(), Error> {
|
pub fn take_snapshot<W: SnapshotWriter + Send>(
|
||||||
let start_header = try!(chain.block_header(&start_block_hash).ok_or(Error::InvalidStartingBlock(start_block_hash)));
|
chain: &BlockChain,
|
||||||
|
block_at: H256,
|
||||||
|
state_db: &HashDB,
|
||||||
|
writer: W,
|
||||||
|
p: &Progress
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let start_header = try!(chain.block_header(&block_at)
|
||||||
|
.ok_or(Error::InvalidStartingBlock(BlockID::Hash(block_at))));
|
||||||
let state_root = start_header.state_root();
|
let state_root = start_header.state_root();
|
||||||
let number = start_header.number();
|
let number = start_header.number();
|
||||||
|
|
||||||
@ -68,8 +110,8 @@ pub fn take_snapshot<W: SnapshotWriter + Send>(chain: &BlockChain, start_block_h
|
|||||||
|
|
||||||
let writer = Mutex::new(writer);
|
let writer = Mutex::new(writer);
|
||||||
let (state_hashes, block_hashes) = try!(scope(|scope| {
|
let (state_hashes, block_hashes) = try!(scope(|scope| {
|
||||||
let block_guard = scope.spawn(|| chunk_blocks(chain, (number, start_block_hash), &writer));
|
let block_guard = scope.spawn(|| chunk_blocks(chain, (number, block_at), &writer, p));
|
||||||
let state_res = chunk_state(state_db, state_root, &writer);
|
let state_res = chunk_state(state_db, state_root, &writer, p);
|
||||||
|
|
||||||
state_res.and_then(|state_hashes| {
|
state_res.and_then(|state_hashes| {
|
||||||
block_guard.join().map(|block_hashes| (state_hashes, block_hashes))
|
block_guard.join().map(|block_hashes| (state_hashes, block_hashes))
|
||||||
@ -83,11 +125,13 @@ pub fn take_snapshot<W: SnapshotWriter + Send>(chain: &BlockChain, start_block_h
|
|||||||
block_hashes: block_hashes,
|
block_hashes: block_hashes,
|
||||||
state_root: *state_root,
|
state_root: *state_root,
|
||||||
block_number: number,
|
block_number: number,
|
||||||
block_hash: start_block_hash,
|
block_hash: block_at,
|
||||||
};
|
};
|
||||||
|
|
||||||
try!(writer.into_inner().finish(manifest_data));
|
try!(writer.into_inner().finish(manifest_data));
|
||||||
|
|
||||||
|
p.done.store(true, Ordering::SeqCst);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,6 +144,7 @@ struct BlockChunker<'a> {
|
|||||||
hashes: Vec<H256>,
|
hashes: Vec<H256>,
|
||||||
snappy_buffer: Vec<u8>,
|
snappy_buffer: Vec<u8>,
|
||||||
writer: &'a Mutex<SnapshotWriter + 'a>,
|
writer: &'a Mutex<SnapshotWriter + 'a>,
|
||||||
|
progress: &'a Progress,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> BlockChunker<'a> {
|
impl<'a> BlockChunker<'a> {
|
||||||
@ -162,7 +207,8 @@ impl<'a> BlockChunker<'a> {
|
|||||||
|
|
||||||
let parent_total_difficulty = parent_details.total_difficulty;
|
let parent_total_difficulty = parent_details.total_difficulty;
|
||||||
|
|
||||||
let mut rlp_stream = RlpStream::new_list(3 + self.rlps.len());
|
let num_entries = self.rlps.len();
|
||||||
|
let mut rlp_stream = RlpStream::new_list(3 + num_entries);
|
||||||
rlp_stream.append(&parent_number).append(&parent_hash).append(&parent_total_difficulty);
|
rlp_stream.append(&parent_number).append(&parent_hash).append(&parent_total_difficulty);
|
||||||
|
|
||||||
for pair in self.rlps.drain(..) {
|
for pair in self.rlps.drain(..) {
|
||||||
@ -178,6 +224,9 @@ impl<'a> BlockChunker<'a> {
|
|||||||
try!(self.writer.lock().write_block_chunk(hash, compressed));
|
try!(self.writer.lock().write_block_chunk(hash, compressed));
|
||||||
trace!(target: "snapshot", "wrote block chunk. hash: {}, size: {}, uncompressed size: {}", hash.hex(), size, raw_data.len());
|
trace!(target: "snapshot", "wrote block chunk. hash: {}, size: {}, uncompressed size: {}", hash.hex(), size, raw_data.len());
|
||||||
|
|
||||||
|
self.progress.size.fetch_add(size, Ordering::SeqCst);
|
||||||
|
self.progress.blocks.fetch_add(num_entries, Ordering::SeqCst);
|
||||||
|
|
||||||
self.hashes.push(hash);
|
self.hashes.push(hash);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -189,7 +238,7 @@ impl<'a> BlockChunker<'a> {
|
|||||||
/// The path parameter is the directory to store the block chunks in.
|
/// The path parameter is the directory to store the block chunks in.
|
||||||
/// This function assumes the directory exists already.
|
/// This function assumes the directory exists already.
|
||||||
/// Returns a list of chunk hashes, with the first having the blocks furthest from the genesis.
|
/// Returns a list of chunk hashes, with the first having the blocks furthest from the genesis.
|
||||||
pub fn chunk_blocks<'a>(chain: &'a BlockChain, start_block_info: (u64, H256), writer: &Mutex<SnapshotWriter + 'a>) -> Result<Vec<H256>, Error> {
|
pub fn chunk_blocks<'a>(chain: &'a BlockChain, start_block_info: (u64, H256), writer: &Mutex<SnapshotWriter + 'a>, progress: &'a Progress) -> Result<Vec<H256>, Error> {
|
||||||
let (start_number, start_hash) = start_block_info;
|
let (start_number, start_hash) = start_block_info;
|
||||||
|
|
||||||
let first_hash = if start_number < SNAPSHOT_BLOCKS {
|
let first_hash = if start_number < SNAPSHOT_BLOCKS {
|
||||||
@ -197,8 +246,7 @@ pub fn chunk_blocks<'a>(chain: &'a BlockChain, start_block_info: (u64, H256), wr
|
|||||||
chain.genesis_hash()
|
chain.genesis_hash()
|
||||||
} else {
|
} else {
|
||||||
let first_num = start_number - SNAPSHOT_BLOCKS;
|
let first_num = start_number - SNAPSHOT_BLOCKS;
|
||||||
chain.block_hash(first_num)
|
try!(chain.block_hash(first_num).ok_or(Error::IncompleteChain))
|
||||||
.expect("number before best block number; whole chain is stored; qed")
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut chunker = BlockChunker {
|
let mut chunker = BlockChunker {
|
||||||
@ -208,6 +256,7 @@ pub fn chunk_blocks<'a>(chain: &'a BlockChain, start_block_info: (u64, H256), wr
|
|||||||
hashes: Vec::new(),
|
hashes: Vec::new(),
|
||||||
snappy_buffer: vec![0; snappy::max_compressed_len(PREFERRED_CHUNK_SIZE)],
|
snappy_buffer: vec![0; snappy::max_compressed_len(PREFERRED_CHUNK_SIZE)],
|
||||||
writer: writer,
|
writer: writer,
|
||||||
|
progress: progress,
|
||||||
};
|
};
|
||||||
|
|
||||||
try!(chunker.chunk_all(first_hash));
|
try!(chunker.chunk_all(first_hash));
|
||||||
@ -222,6 +271,7 @@ struct StateChunker<'a> {
|
|||||||
cur_size: usize,
|
cur_size: usize,
|
||||||
snappy_buffer: Vec<u8>,
|
snappy_buffer: Vec<u8>,
|
||||||
writer: &'a Mutex<SnapshotWriter + 'a>,
|
writer: &'a Mutex<SnapshotWriter + 'a>,
|
||||||
|
progress: &'a Progress,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> StateChunker<'a> {
|
impl<'a> StateChunker<'a> {
|
||||||
@ -249,7 +299,8 @@ impl<'a> StateChunker<'a> {
|
|||||||
// Write out the buffer to disk, pushing the created chunk's hash to
|
// Write out the buffer to disk, pushing the created chunk's hash to
|
||||||
// the list.
|
// the list.
|
||||||
fn write_chunk(&mut self) -> Result<(), Error> {
|
fn write_chunk(&mut self) -> Result<(), Error> {
|
||||||
let mut stream = RlpStream::new_list(self.rlps.len());
|
let num_entries = self.rlps.len();
|
||||||
|
let mut stream = RlpStream::new_list(num_entries);
|
||||||
for rlp in self.rlps.drain(..) {
|
for rlp in self.rlps.drain(..) {
|
||||||
stream.append_raw(&rlp, 1);
|
stream.append_raw(&rlp, 1);
|
||||||
}
|
}
|
||||||
@ -263,6 +314,9 @@ impl<'a> StateChunker<'a> {
|
|||||||
try!(self.writer.lock().write_state_chunk(hash, compressed));
|
try!(self.writer.lock().write_state_chunk(hash, compressed));
|
||||||
trace!(target: "snapshot", "wrote state chunk. size: {}, uncompressed size: {}", compressed_size, raw_data.len());
|
trace!(target: "snapshot", "wrote state chunk. size: {}, uncompressed size: {}", compressed_size, raw_data.len());
|
||||||
|
|
||||||
|
self.progress.accounts.fetch_add(num_entries, Ordering::SeqCst);
|
||||||
|
self.progress.size.fetch_add(compressed_size, Ordering::SeqCst);
|
||||||
|
|
||||||
self.hashes.push(hash);
|
self.hashes.push(hash);
|
||||||
self.cur_size = 0;
|
self.cur_size = 0;
|
||||||
|
|
||||||
@ -275,7 +329,7 @@ impl<'a> StateChunker<'a> {
|
|||||||
///
|
///
|
||||||
/// Returns a list of hashes of chunks created, or any error it may
|
/// Returns a list of hashes of chunks created, or any error it may
|
||||||
/// have encountered.
|
/// have encountered.
|
||||||
pub fn chunk_state<'a>(db: &HashDB, root: &H256, writer: &Mutex<SnapshotWriter + 'a>) -> Result<Vec<H256>, Error> {
|
pub fn chunk_state<'a>(db: &HashDB, root: &H256, writer: &Mutex<SnapshotWriter + 'a>, progress: &'a Progress) -> Result<Vec<H256>, Error> {
|
||||||
let account_trie = try!(TrieDB::new(db, &root));
|
let account_trie = try!(TrieDB::new(db, &root));
|
||||||
|
|
||||||
let mut chunker = StateChunker {
|
let mut chunker = StateChunker {
|
||||||
@ -284,10 +338,9 @@ pub fn chunk_state<'a>(db: &HashDB, root: &H256, writer: &Mutex<SnapshotWriter +
|
|||||||
cur_size: 0,
|
cur_size: 0,
|
||||||
snappy_buffer: vec![0; snappy::max_compressed_len(PREFERRED_CHUNK_SIZE)],
|
snappy_buffer: vec![0; snappy::max_compressed_len(PREFERRED_CHUNK_SIZE)],
|
||||||
writer: writer,
|
writer: writer,
|
||||||
|
progress: progress,
|
||||||
};
|
};
|
||||||
|
|
||||||
trace!(target: "snapshot", "beginning state chunking");
|
|
||||||
|
|
||||||
// account_key here is the address' hash.
|
// account_key here is the address' hash.
|
||||||
for (account_key, account_data) in account_trie.iter() {
|
for (account_key, account_data) in account_trie.iter() {
|
||||||
let account = Account::from_thin_rlp(account_data);
|
let account = Account::from_thin_rlp(account_data);
|
||||||
@ -383,6 +436,7 @@ impl StateRebuilder {
|
|||||||
let chunk_size = account_fat_rlps.len() / ::num_cpus::get() + 1;
|
let chunk_size = account_fat_rlps.len() / ::num_cpus::get() + 1;
|
||||||
|
|
||||||
// build account tries in parallel.
|
// build account tries in parallel.
|
||||||
|
// Todo [rob] keep a thread pool around so we don't do this per-chunk.
|
||||||
try!(scope(|scope| {
|
try!(scope(|scope| {
|
||||||
let mut handles = Vec::new();
|
let mut handles = Vec::new();
|
||||||
for (account_chunk, out_pairs_chunk) in account_fat_rlps.chunks(chunk_size).zip(pairs.chunks_mut(chunk_size)) {
|
for (account_chunk, out_pairs_chunk) in account_fat_rlps.chunks(chunk_size).zip(pairs.chunks_mut(chunk_size)) {
|
||||||
|
@ -20,7 +20,7 @@ use devtools::RandomTempPath;
|
|||||||
|
|
||||||
use blockchain::generator::{ChainGenerator, ChainIterator, BlockFinalizer};
|
use blockchain::generator::{ChainGenerator, ChainIterator, BlockFinalizer};
|
||||||
use blockchain::BlockChain;
|
use blockchain::BlockChain;
|
||||||
use snapshot::{chunk_blocks, BlockRebuilder};
|
use snapshot::{chunk_blocks, BlockRebuilder, Progress};
|
||||||
use snapshot::io::{PackedReader, PackedWriter, SnapshotReader, SnapshotWriter};
|
use snapshot::io::{PackedReader, PackedWriter, SnapshotReader, SnapshotWriter};
|
||||||
|
|
||||||
use util::{Mutex, snappy};
|
use util::{Mutex, snappy};
|
||||||
@ -55,7 +55,7 @@ fn chunk_and_restore(amount: u64) {
|
|||||||
|
|
||||||
// snapshot it.
|
// snapshot it.
|
||||||
let writer = Mutex::new(PackedWriter::new(&snapshot_path).unwrap());
|
let writer = Mutex::new(PackedWriter::new(&snapshot_path).unwrap());
|
||||||
let block_hashes = chunk_blocks(&bc, (amount, best_hash), &writer).unwrap();
|
let block_hashes = chunk_blocks(&bc, (amount, best_hash), &writer, &Progress::new()).unwrap();
|
||||||
writer.into_inner().finish(::snapshot::ManifestData {
|
writer.into_inner().finish(::snapshot::ManifestData {
|
||||||
state_hashes: Vec::new(),
|
state_hashes: Vec::new(),
|
||||||
block_hashes: block_hashes,
|
block_hashes: block_hashes,
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
//! State snapshotting tests.
|
//! State snapshotting tests.
|
||||||
|
|
||||||
use snapshot::{chunk_state, StateRebuilder};
|
use snapshot::{chunk_state, Progress, StateRebuilder};
|
||||||
use snapshot::io::{PackedReader, PackedWriter, SnapshotReader, SnapshotWriter};
|
use snapshot::io::{PackedReader, PackedWriter, SnapshotReader, SnapshotWriter};
|
||||||
use super::helpers::{compare_dbs, StateProducer};
|
use super::helpers::{compare_dbs, StateProducer};
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ fn snap_and_restore() {
|
|||||||
let state_root = producer.state_root();
|
let state_root = producer.state_root();
|
||||||
let writer = Mutex::new(PackedWriter::new(&snap_file).unwrap());
|
let writer = Mutex::new(PackedWriter::new(&snap_file).unwrap());
|
||||||
|
|
||||||
let state_hashes = chunk_state(&old_db, &state_root, &writer).unwrap();
|
let state_hashes = chunk_state(&old_db, &state_root, &writer, &Progress::new()).unwrap();
|
||||||
|
|
||||||
writer.into_inner().finish(::snapshot::ManifestData {
|
writer.into_inner().finish(::snapshot::ManifestData {
|
||||||
state_hashes: state_hashes,
|
state_hashes: state_hashes,
|
||||||
|
@ -40,7 +40,8 @@ pub fn verify_block_basic(header: &Header, bytes: &[u8], engine: &Engine) -> Res
|
|||||||
try!(verify_header(&header, engine));
|
try!(verify_header(&header, engine));
|
||||||
try!(verify_block_integrity(bytes, &header.transactions_root, &header.uncles_hash));
|
try!(verify_block_integrity(bytes, &header.transactions_root, &header.uncles_hash));
|
||||||
try!(engine.verify_block_basic(&header, Some(bytes)));
|
try!(engine.verify_block_basic(&header, Some(bytes)));
|
||||||
for u in Rlp::new(bytes).at(2).iter().map(|rlp| rlp.as_val::<Header>()) {
|
for u in try!(UntrustedRlp::new(bytes).at(2)).iter().map(|rlp| rlp.as_val::<Header>()) {
|
||||||
|
let u = try!(u);
|
||||||
try!(verify_header(&u, engine));
|
try!(verify_header(&u, engine));
|
||||||
try!(engine.verify_block_basic(&u, None));
|
try!(engine.verify_block_basic(&u, None));
|
||||||
}
|
}
|
||||||
@ -58,8 +59,8 @@ pub fn verify_block_basic(header: &Header, bytes: &[u8], engine: &Engine) -> Res
|
|||||||
/// Returns a `PreverifiedBlock` structure populated with transactions
|
/// Returns a `PreverifiedBlock` structure populated with transactions
|
||||||
pub fn verify_block_unordered(header: Header, bytes: Bytes, engine: &Engine) -> Result<PreverifiedBlock, Error> {
|
pub fn verify_block_unordered(header: Header, bytes: Bytes, engine: &Engine) -> Result<PreverifiedBlock, Error> {
|
||||||
try!(engine.verify_block_unordered(&header, Some(&bytes)));
|
try!(engine.verify_block_unordered(&header, Some(&bytes)));
|
||||||
for u in Rlp::new(&bytes).at(2).iter().map(|rlp| rlp.as_val::<Header>()) {
|
for u in try!(UntrustedRlp::new(&bytes).at(2)).iter().map(|rlp| rlp.as_val::<Header>()) {
|
||||||
try!(engine.verify_block_unordered(&u, None));
|
try!(engine.verify_block_unordered(&try!(u), None));
|
||||||
}
|
}
|
||||||
// Verify transactions.
|
// Verify transactions.
|
||||||
let mut transactions = Vec::new();
|
let mut transactions = Vec::new();
|
||||||
@ -84,7 +85,7 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &
|
|||||||
try!(verify_parent(&header, &parent));
|
try!(verify_parent(&header, &parent));
|
||||||
try!(engine.verify_block_family(&header, &parent, Some(bytes)));
|
try!(engine.verify_block_family(&header, &parent, Some(bytes)));
|
||||||
|
|
||||||
let num_uncles = Rlp::new(bytes).at(2).item_count();
|
let num_uncles = try!(UntrustedRlp::new(bytes).at(2)).item_count();
|
||||||
if num_uncles != 0 {
|
if num_uncles != 0 {
|
||||||
if num_uncles > engine.maximum_uncle_count() {
|
if num_uncles > engine.maximum_uncle_count() {
|
||||||
return Err(From::from(BlockError::TooManyUncles(OutOfBounds { min: None, max: Some(engine.maximum_uncle_count()), found: num_uncles })));
|
return Err(From::from(BlockError::TooManyUncles(OutOfBounds { min: None, max: Some(engine.maximum_uncle_count()), found: num_uncles })));
|
||||||
@ -106,7 +107,8 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for uncle in Rlp::new(bytes).at(2).iter().map(|rlp| rlp.as_val::<Header>()) {
|
for uncle in try!(UntrustedRlp::new(bytes).at(2)).iter().map(|rlp| rlp.as_val::<Header>()) {
|
||||||
|
let uncle = try!(uncle);
|
||||||
if excluded.contains(&uncle.hash()) {
|
if excluded.contains(&uncle.hash()) {
|
||||||
return Err(From::from(BlockError::UncleInChain(uncle.hash())))
|
return Err(From::from(BlockError::UncleInChain(uncle.hash())))
|
||||||
}
|
}
|
||||||
@ -210,13 +212,13 @@ fn verify_parent(header: &Header, parent: &Header) -> Result<(), Error> {
|
|||||||
|
|
||||||
/// Verify block data against header: transactions root and uncles hash.
|
/// Verify block data against header: transactions root and uncles hash.
|
||||||
fn verify_block_integrity(block: &[u8], transactions_root: &H256, uncles_hash: &H256) -> Result<(), Error> {
|
fn verify_block_integrity(block: &[u8], transactions_root: &H256, uncles_hash: &H256) -> Result<(), Error> {
|
||||||
let block = Rlp::new(block);
|
let block = UntrustedRlp::new(block);
|
||||||
let tx = block.at(1);
|
let tx = try!(block.at(1));
|
||||||
let expected_root = &ordered_trie_root(tx.iter().map(|r| r.as_raw().to_vec()).collect()); //TODO: get rid of vectors here
|
let expected_root = &ordered_trie_root(tx.iter().map(|r| r.as_raw().to_vec()).collect()); //TODO: get rid of vectors here
|
||||||
if expected_root != transactions_root {
|
if expected_root != transactions_root {
|
||||||
return Err(From::from(BlockError::InvalidTransactionsRoot(Mismatch { expected: expected_root.clone(), found: transactions_root.clone() })))
|
return Err(From::from(BlockError::InvalidTransactionsRoot(Mismatch { expected: expected_root.clone(), found: transactions_root.clone() })))
|
||||||
}
|
}
|
||||||
let expected_uncles = &block.at(2).as_raw().sha3();
|
let expected_uncles = &try!(block.at(2)).as_raw().sha3();
|
||||||
if expected_uncles != uncles_hash {
|
if expected_uncles != uncles_hash {
|
||||||
return Err(From::from(BlockError::InvalidUnclesHash(Mismatch { expected: expected_uncles.clone(), found: uncles_hash.clone() })))
|
return Err(From::from(BlockError::InvalidUnclesHash(Mismatch { expected: expected_uncles.clone(), found: uncles_hash.clone() })))
|
||||||
}
|
}
|
||||||
|
@ -48,10 +48,10 @@ macro_rules! impl_hash {
|
|||||||
0 => $inner::from(0),
|
0 => $inner::from(0),
|
||||||
2 if value == "0x" => $inner::from(0),
|
2 if value == "0x" => $inner::from(0),
|
||||||
_ if value.starts_with("0x") => try!($inner::from_str(&value[2..]).map_err(|_| {
|
_ if value.starts_with("0x") => try!($inner::from_str(&value[2..]).map_err(|_| {
|
||||||
Error::custom(format!("Invalid hex value {}.", value).as_ref())
|
Error::custom(format!("Invalid hex value {}.", value).as_str())
|
||||||
})),
|
})),
|
||||||
_ => try!($inner::from_str(value).map_err(|_| {
|
_ => try!($inner::from_str(value).map_err(|_| {
|
||||||
Error::custom(format!("Invalid hex value {}.", value).as_ref())
|
Error::custom(format!("Invalid hex value {}.", value).as_str())
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -70,10 +70,10 @@ impl Visitor for UintVisitor {
|
|||||||
0 => U256::from(0),
|
0 => U256::from(0),
|
||||||
2 if value.starts_with("0x") => U256::from(0),
|
2 if value.starts_with("0x") => U256::from(0),
|
||||||
_ if value.starts_with("0x") => try!(U256::from_str(&value[2..]).map_err(|_| {
|
_ if value.starts_with("0x") => try!(U256::from_str(&value[2..]).map_err(|_| {
|
||||||
Error::custom(format!("Invalid hex value {}.", value).as_ref())
|
Error::custom(format!("Invalid hex value {}.", value).as_str())
|
||||||
})),
|
})),
|
||||||
_ => try!(U256::from_dec_str(value).map_err(|_| {
|
_ => try!(U256::from_dec_str(value).map_err(|_| {
|
||||||
Error::custom(format!("Invalid decimal value {}.", value).as_ref())
|
Error::custom(format!("Invalid decimal value {}.", value).as_str())
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -231,6 +231,12 @@ Import/Export Options:
|
|||||||
--format FORMAT For import/export in given format. FORMAT must be
|
--format FORMAT For import/export in given format. FORMAT must be
|
||||||
one of 'hex' and 'binary'.
|
one of 'hex' and 'binary'.
|
||||||
|
|
||||||
|
Snapshot Options:
|
||||||
|
--at BLOCK Take a snapshot at the given block, which may be an
|
||||||
|
index, hash, or 'latest'. Note that taking snapshots at
|
||||||
|
non-recent blocks will only work with --pruning archive
|
||||||
|
[default: latest]
|
||||||
|
|
||||||
Virtual Machine Options:
|
Virtual Machine Options:
|
||||||
--jitvm Enable the JIT VM.
|
--jitvm Enable the JIT VM.
|
||||||
|
|
||||||
@ -365,6 +371,7 @@ pub struct Args {
|
|||||||
pub flag_version: bool,
|
pub flag_version: bool,
|
||||||
pub flag_from: String,
|
pub flag_from: String,
|
||||||
pub flag_to: String,
|
pub flag_to: String,
|
||||||
|
pub flag_at: String,
|
||||||
pub flag_format: Option<String>,
|
pub flag_format: Option<String>,
|
||||||
pub flag_jitvm: bool,
|
pub flag_jitvm: bool,
|
||||||
pub flag_log_file: Option<String>,
|
pub flag_log_file: Option<String>,
|
||||||
|
@ -171,6 +171,7 @@ impl Configuration {
|
|||||||
file_path: self.args.arg_file.clone(),
|
file_path: self.args.arg_file.clone(),
|
||||||
wal: wal,
|
wal: wal,
|
||||||
kind: snapshot::Kind::Take,
|
kind: snapshot::Kind::Take,
|
||||||
|
block_at: try!(to_block_id(&self.args.flag_at)),
|
||||||
};
|
};
|
||||||
Cmd::Snapshot(snapshot_cmd)
|
Cmd::Snapshot(snapshot_cmd)
|
||||||
} else if self.args.cmd_restore {
|
} else if self.args.cmd_restore {
|
||||||
@ -186,6 +187,7 @@ impl Configuration {
|
|||||||
file_path: self.args.arg_file.clone(),
|
file_path: self.args.arg_file.clone(),
|
||||||
wal: wal,
|
wal: wal,
|
||||||
kind: snapshot::Kind::Restore,
|
kind: snapshot::Kind::Restore,
|
||||||
|
block_at: try!(to_block_id("latest")), // unimportant.
|
||||||
};
|
};
|
||||||
Cmd::Snapshot(restore_cmd)
|
Cmd::Snapshot(restore_cmd)
|
||||||
} else {
|
} else {
|
||||||
|
@ -19,12 +19,15 @@
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use ethcore_logger::{setup_log, Config as LogConfig};
|
use ethcore_logger::{setup_log, Config as LogConfig};
|
||||||
use ethcore::snapshot::{RestorationStatus, SnapshotService};
|
use ethcore::snapshot::{Progress, RestorationStatus, SnapshotService};
|
||||||
use ethcore::snapshot::io::{SnapshotReader, PackedReader, PackedWriter};
|
use ethcore::snapshot::io::{SnapshotReader, PackedReader, PackedWriter};
|
||||||
use ethcore::service::ClientService;
|
use ethcore::service::ClientService;
|
||||||
use ethcore::client::{Mode, DatabaseCompactionProfile, Switch, VMType};
|
use ethcore::client::{Mode, DatabaseCompactionProfile, Switch, VMType};
|
||||||
use ethcore::miner::Miner;
|
use ethcore::miner::Miner;
|
||||||
|
use ethcore::ids::BlockID;
|
||||||
|
|
||||||
use cache::CacheConfig;
|
use cache::CacheConfig;
|
||||||
use params::{SpecType, Pruning};
|
use params::{SpecType, Pruning};
|
||||||
use helpers::{to_client_config, execute_upgrades};
|
use helpers::{to_client_config, execute_upgrades};
|
||||||
@ -56,6 +59,7 @@ pub struct SnapshotCommand {
|
|||||||
pub file_path: Option<String>,
|
pub file_path: Option<String>,
|
||||||
pub wal: bool,
|
pub wal: bool,
|
||||||
pub kind: Kind,
|
pub kind: Kind,
|
||||||
|
pub block_at: BlockID,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SnapshotCommand {
|
impl SnapshotCommand {
|
||||||
@ -168,6 +172,7 @@ impl SnapshotCommand {
|
|||||||
pub fn take_snapshot(self) -> Result<(), String> {
|
pub fn take_snapshot(self) -> Result<(), String> {
|
||||||
let file_path = try!(self.file_path.clone().ok_or("No file path provided.".to_owned()));
|
let file_path = try!(self.file_path.clone().ok_or("No file path provided.".to_owned()));
|
||||||
let file_path: PathBuf = file_path.into();
|
let file_path: PathBuf = file_path.into();
|
||||||
|
let block_at = self.block_at.clone();
|
||||||
let (service, _panic_handler) = try!(self.start_service());
|
let (service, _panic_handler) = try!(self.start_service());
|
||||||
|
|
||||||
warn!("Snapshots are currently experimental. File formats may be subject to change.");
|
warn!("Snapshots are currently experimental. File formats may be subject to change.");
|
||||||
@ -175,11 +180,35 @@ impl SnapshotCommand {
|
|||||||
let writer = try!(PackedWriter::new(&file_path)
|
let writer = try!(PackedWriter::new(&file_path)
|
||||||
.map_err(|e| format!("Failed to open snapshot writer: {}", e)));
|
.map_err(|e| format!("Failed to open snapshot writer: {}", e)));
|
||||||
|
|
||||||
if let Err(e) = service.client().take_snapshot(writer) {
|
let progress = Arc::new(Progress::new());
|
||||||
|
let p = progress.clone();
|
||||||
|
let informant_handle = ::std::thread::spawn(move || {
|
||||||
|
::std::thread::sleep(Duration::from_secs(5));
|
||||||
|
|
||||||
|
let mut last_size = 0;
|
||||||
|
while !p.done() {
|
||||||
|
let cur_size = p.size();
|
||||||
|
if cur_size != last_size {
|
||||||
|
last_size = cur_size;
|
||||||
|
info!("Snapshot: {} accounts {} blocks {} bytes", p.accounts(), p.blocks(), p.size());
|
||||||
|
} else {
|
||||||
|
info!("Snapshot: No progress since last update.");
|
||||||
|
}
|
||||||
|
|
||||||
|
::std::thread::sleep(Duration::from_secs(5));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Err(e) = service.client().take_snapshot(writer, block_at, &*progress) {
|
||||||
let _ = ::std::fs::remove_file(&file_path);
|
let _ = ::std::fs::remove_file(&file_path);
|
||||||
return Err(format!("Encountered fatal error while creating snapshot: {}", e));
|
return Err(format!("Encountered fatal error while creating snapshot: {}", e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info!("snapshot creation complete");
|
||||||
|
|
||||||
|
assert!(progress.done());
|
||||||
|
try!(informant_handle.join().map_err(|_| "failed to join logger thread"));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ build = "build.rs"
|
|||||||
log = "0.3"
|
log = "0.3"
|
||||||
serde = "0.7.0"
|
serde = "0.7.0"
|
||||||
serde_json = "0.7.0"
|
serde_json = "0.7.0"
|
||||||
jsonrpc-core = "2.0"
|
jsonrpc-core = "2.1"
|
||||||
jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc-http-server.git" }
|
jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc-http-server.git" }
|
||||||
ethcore-io = { path = "../util/io" }
|
ethcore-io = { path = "../util/io" }
|
||||||
ethcore-util = { path = "../util" }
|
ethcore-util = { path = "../util" }
|
||||||
|
96
rpc/src/v1/helpers/dispatch.rs
Normal file
96
rpc/src/v1/helpers/dispatch.rs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// 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/>.
|
||||||
|
|
||||||
|
use util::{Address, H256, U256, Uint};
|
||||||
|
use util::rlp::encode;
|
||||||
|
use util::bytes::ToPretty;
|
||||||
|
use ethcore::miner::MinerService;
|
||||||
|
use ethcore::client::MiningBlockChainClient;
|
||||||
|
use ethcore::transaction::{Action, SignedTransaction, Transaction};
|
||||||
|
use ethcore::account_provider::AccountProvider;
|
||||||
|
use jsonrpc_core::{Error, Value, to_value};
|
||||||
|
use v1::helpers::TransactionRequest;
|
||||||
|
use v1::types::{H256 as RpcH256, H520 as RpcH520};
|
||||||
|
use v1::helpers::errors;
|
||||||
|
|
||||||
|
fn prepare_transaction<C, M>(client: &C, miner: &M, request: TransactionRequest) -> Transaction where C: MiningBlockChainClient, M: MinerService {
|
||||||
|
Transaction {
|
||||||
|
nonce: request.nonce
|
||||||
|
.or_else(|| miner
|
||||||
|
.last_nonce(&request.from)
|
||||||
|
.map(|nonce| nonce + U256::one()))
|
||||||
|
.unwrap_or_else(|| client.latest_nonce(&request.from)),
|
||||||
|
|
||||||
|
action: request.to.map_or(Action::Create, Action::Call),
|
||||||
|
gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()),
|
||||||
|
gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(client, miner)),
|
||||||
|
value: request.value.unwrap_or_else(U256::zero),
|
||||||
|
data: request.data.map_or_else(Vec::new, |b| b.to_vec()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dispatch_transaction<C, M>(client: &C, miner: &M, signed_transaction: SignedTransaction) -> Result<Value, Error>
|
||||||
|
where C: MiningBlockChainClient, M: MinerService {
|
||||||
|
let hash = RpcH256::from(signed_transaction.hash());
|
||||||
|
|
||||||
|
let import = miner.import_own_transaction(client, signed_transaction);
|
||||||
|
|
||||||
|
import
|
||||||
|
.map_err(errors::from_transaction_error)
|
||||||
|
.and_then(|_| to_value(&hash))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn signature_with_password(accounts: &AccountProvider, address: Address, hash: H256, pass: String) -> Result<Value, Error> {
|
||||||
|
accounts.sign_with_password(address, pass, hash)
|
||||||
|
.map_err(errors::from_password_error)
|
||||||
|
.and_then(|hash| to_value(&RpcH520::from(hash)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unlock_sign_and_dispatch<C, M>(client: &C, miner: &M, request: TransactionRequest, account_provider: &AccountProvider, password: String) -> Result<Value, Error>
|
||||||
|
where C: MiningBlockChainClient, M: MinerService {
|
||||||
|
|
||||||
|
let address = request.from;
|
||||||
|
let signed_transaction = {
|
||||||
|
let t = prepare_transaction(client, miner, request);
|
||||||
|
let hash = t.hash();
|
||||||
|
let signature = try!(account_provider.sign_with_password(address, password, hash).map_err(errors::from_password_error));
|
||||||
|
t.with_signature(signature)
|
||||||
|
};
|
||||||
|
|
||||||
|
trace!(target: "miner", "send_transaction: dispatching tx: {}", encode(&signed_transaction).to_vec().pretty());
|
||||||
|
dispatch_transaction(&*client, &*miner, signed_transaction)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sign_and_dispatch<C, M>(client: &C, miner: &M, request: TransactionRequest, account_provider: &AccountProvider, address: Address) -> Result<Value, Error>
|
||||||
|
where C: MiningBlockChainClient, M: MinerService {
|
||||||
|
|
||||||
|
let signed_transaction = {
|
||||||
|
let t = prepare_transaction(client, miner, request);
|
||||||
|
let hash = t.hash();
|
||||||
|
let signature = try!(account_provider.sign(address, hash).map_err(errors::from_signing_error));
|
||||||
|
t.with_signature(signature)
|
||||||
|
};
|
||||||
|
|
||||||
|
trace!(target: "miner", "send_transaction: dispatching tx: {}", encode(&signed_transaction).to_vec().pretty());
|
||||||
|
dispatch_transaction(&*client, &*miner, signed_transaction)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn default_gas_price<C, M>(client: &C, miner: &M) -> U256 where C: MiningBlockChainClient, M: MinerService {
|
||||||
|
client
|
||||||
|
.gas_price_statistics(100, 8)
|
||||||
|
.map(|x| x[4])
|
||||||
|
.unwrap_or_else(|_| miner.sensible_gas_price())
|
||||||
|
}
|
188
rpc/src/v1/helpers/errors.rs
Normal file
188
rpc/src/v1/helpers/errors.rs
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
// 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/>.
|
||||||
|
|
||||||
|
//! RPC Error codes and error objects
|
||||||
|
|
||||||
|
macro_rules! rpc_unimplemented {
|
||||||
|
() => (Err(::v1::helpers::errors::unimplemented()))
|
||||||
|
}
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
use ethcore::error::Error as EthcoreError;
|
||||||
|
use ethcore::account_provider::{Error as AccountError};
|
||||||
|
use jsonrpc_core::{Error, ErrorCode, Value};
|
||||||
|
|
||||||
|
mod codes {
|
||||||
|
// NOTE [ToDr] Codes from [-32099, -32000]
|
||||||
|
pub const UNSUPPORTED_REQUEST: i64 = -32000;
|
||||||
|
pub const NO_WORK: i64 = -32001;
|
||||||
|
pub const NO_AUTHOR: i64 = -32002;
|
||||||
|
pub const UNKNOWN_ERROR: i64 = -32009;
|
||||||
|
pub const TRANSACTION_ERROR: i64 = -32010;
|
||||||
|
pub const ACCOUNT_LOCKED: i64 = -32020;
|
||||||
|
pub const PASSWORD_INVALID: i64 = -32021;
|
||||||
|
pub const ACCOUNT_ERROR: i64 = -32023;
|
||||||
|
pub const SIGNER_DISABLED: i64 = -32030;
|
||||||
|
pub const REQUEST_REJECTED: i64 = -32040;
|
||||||
|
pub const REQUEST_NOT_FOUND: i64 = -32041;
|
||||||
|
pub const COMPILATION_ERROR: i64 = -32050;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unimplemented() -> Error {
|
||||||
|
Error {
|
||||||
|
code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST),
|
||||||
|
message: "This request is not implemented yet. Please create an issue on Github repo.".into(),
|
||||||
|
data: None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn request_not_found() -> Error {
|
||||||
|
Error {
|
||||||
|
code: ErrorCode::ServerError(codes::REQUEST_NOT_FOUND),
|
||||||
|
message: "Request not found.".into(),
|
||||||
|
data: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn request_rejected() -> Error {
|
||||||
|
Error {
|
||||||
|
code: ErrorCode::ServerError(codes::REQUEST_REJECTED),
|
||||||
|
message: "Request has been rejected.".into(),
|
||||||
|
data: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn account<T: fmt::Debug>(error: &str, details: T) -> Error {
|
||||||
|
Error {
|
||||||
|
code: ErrorCode::ServerError(codes::ACCOUNT_ERROR),
|
||||||
|
message: error.into(),
|
||||||
|
data: Some(Value::String(format!("{:?}", details))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compilation<T: fmt::Debug>(error: T) -> Error {
|
||||||
|
Error {
|
||||||
|
code: ErrorCode::ServerError(codes::COMPILATION_ERROR),
|
||||||
|
message: "Error while compiling code.".into(),
|
||||||
|
data: Some(Value::String(format!("{:?}", error))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn internal<T: fmt::Debug>(error: &str, data: T) -> Error {
|
||||||
|
Error {
|
||||||
|
code: ErrorCode::InternalError,
|
||||||
|
message: format!("Internal error occurred: {}", error),
|
||||||
|
data: Some(Value::String(format!("{:?}", data))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn invalid_params<T: fmt::Debug>(param: &str, details: T) -> Error {
|
||||||
|
Error {
|
||||||
|
code: ErrorCode::InvalidParams,
|
||||||
|
message: format!("Couldn't parse parameters: {}", param),
|
||||||
|
data: Some(Value::String(format!("{:?}", details))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn state_pruned() -> Error {
|
||||||
|
Error {
|
||||||
|
code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST),
|
||||||
|
message: "This request is not supported because your node is running with state pruning. Run with --pruning=archive.".into(),
|
||||||
|
data: None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn no_work() -> Error {
|
||||||
|
Error {
|
||||||
|
code: ErrorCode::ServerError(codes::NO_WORK),
|
||||||
|
message: "Still syncing.".into(),
|
||||||
|
data: None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn no_author() -> Error {
|
||||||
|
Error {
|
||||||
|
code: ErrorCode::ServerError(codes::NO_AUTHOR),
|
||||||
|
message: "Author not configured. Run Parity with --author to configure.".into(),
|
||||||
|
data: None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn signer_disabled() -> Error {
|
||||||
|
Error {
|
||||||
|
code: ErrorCode::ServerError(codes::SIGNER_DISABLED),
|
||||||
|
message: "Trusted Signer is disabled. This API is not available.".into(),
|
||||||
|
data: None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_signing_error(error: AccountError) -> Error {
|
||||||
|
Error {
|
||||||
|
code: ErrorCode::ServerError(codes::ACCOUNT_LOCKED),
|
||||||
|
message: "Your account is locked. Unlock the account via CLI, personal_unlockAccount or use Trusted Signer.".into(),
|
||||||
|
data: Some(Value::String(format!("{:?}", error))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_password_error(error: AccountError) -> Error {
|
||||||
|
Error {
|
||||||
|
code: ErrorCode::ServerError(codes::PASSWORD_INVALID),
|
||||||
|
message: "Account password is invalid or account does not exist.".into(),
|
||||||
|
data: Some(Value::String(format!("{:?}", error))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_transaction_error(error: EthcoreError) -> Error {
|
||||||
|
use ethcore::error::TransactionError::*;
|
||||||
|
|
||||||
|
if let EthcoreError::Transaction(e) = error {
|
||||||
|
let msg = match e {
|
||||||
|
AlreadyImported => "Transaction with the same hash was already imported.".into(),
|
||||||
|
Old => "Transaction nonce is too low. Try incrementing the nonce.".into(),
|
||||||
|
TooCheapToReplace => {
|
||||||
|
"Transaction fee is too low. There is another transaction with same nonce in the queue. Try increasing the fee or incrementing the nonce.".into()
|
||||||
|
},
|
||||||
|
LimitReached => {
|
||||||
|
"There are too many transactions in the queue. Your transaction was dropped due to limit. Try increasing the fee.".into()
|
||||||
|
},
|
||||||
|
InsufficientGasPrice { minimal, got } => {
|
||||||
|
format!("Transaction fee is too low. It does not satisfy your node's minimal fee (minimal: {}, got: {}). Try increasing the fee.", minimal, got)
|
||||||
|
},
|
||||||
|
InsufficientBalance { balance, cost } => {
|
||||||
|
format!("Insufficient funds. Account you try to send transaction from does not have enough funds. Required {} and got: {}.", cost, balance)
|
||||||
|
},
|
||||||
|
GasLimitExceeded { limit, got } => {
|
||||||
|
format!("Transaction cost exceeds current gas limit. Limit: {}, got: {}. Try decreasing supplied gas.", limit, got)
|
||||||
|
},
|
||||||
|
InvalidGasLimit(_) => "Supplied gas is beyond limit.".into(),
|
||||||
|
};
|
||||||
|
Error {
|
||||||
|
code: ErrorCode::ServerError(codes::TRANSACTION_ERROR),
|
||||||
|
message: msg,
|
||||||
|
data: None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Error {
|
||||||
|
code: ErrorCode::ServerError(codes::UNKNOWN_ERROR),
|
||||||
|
message: "Unknown error when sending transaction.".into(),
|
||||||
|
data: Some(Value::String(format!("{:?}", error))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -14,6 +14,10 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
pub mod errors;
|
||||||
|
pub mod dispatch;
|
||||||
|
pub mod params;
|
||||||
mod poll_manager;
|
mod poll_manager;
|
||||||
mod poll_filter;
|
mod poll_filter;
|
||||||
mod requests;
|
mod requests;
|
||||||
|
53
rpc/src/v1/helpers/params.rs
Normal file
53
rpc/src/v1/helpers/params.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// 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/>.
|
||||||
|
|
||||||
|
//! Parameters parsing helpers
|
||||||
|
|
||||||
|
use serde;
|
||||||
|
use jsonrpc_core::{Error, Params, from_params};
|
||||||
|
use v1::types::BlockNumber;
|
||||||
|
use v1::helpers::errors;
|
||||||
|
|
||||||
|
pub fn expect_no_params(params: Params) -> Result<(), Error> {
|
||||||
|
match params {
|
||||||
|
Params::None => Ok(()),
|
||||||
|
p => Err(errors::invalid_params("No parameters were expected", p)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn params_len(params: &Params) -> usize {
|
||||||
|
match params {
|
||||||
|
&Params::Array(ref vec) => vec.len(),
|
||||||
|
_ => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialize request parameters with optional second parameter `BlockNumber` defaulting to `BlockNumber::Latest`.
|
||||||
|
pub fn from_params_default_second<F>(params: Params) -> Result<(F, BlockNumber, ), Error> where F: serde::de::Deserialize {
|
||||||
|
match params_len(¶ms) {
|
||||||
|
1 => from_params::<(F, )>(params).map(|(f,)| (f, BlockNumber::Latest)),
|
||||||
|
_ => from_params::<(F, BlockNumber)>(params),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialize request parameters with optional third parameter `BlockNumber` defaulting to `BlockNumber::Latest`.
|
||||||
|
pub fn from_params_default_third<F1, F2>(params: Params) -> Result<(F1, F2, BlockNumber, ), Error> where F1: serde::de::Deserialize, F2: serde::de::Deserialize {
|
||||||
|
match params_len(¶ms) {
|
||||||
|
2 => from_params::<(F1, F2, )>(params).map(|(f1, f2)| (f1, f2, BlockNumber::Latest)),
|
||||||
|
_ => from_params::<(F1, F2, BlockNumber)>(params)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -43,8 +43,9 @@ use ethcore::filter::Filter as EthcoreFilter;
|
|||||||
use self::ethash::SeedHashCompute;
|
use self::ethash::SeedHashCompute;
|
||||||
use v1::traits::Eth;
|
use v1::traits::Eth;
|
||||||
use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, CallRequest, Index, Filter, Log, Receipt, H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256};
|
use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, CallRequest, Index, Filter, Log, Receipt, H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256};
|
||||||
use v1::helpers::CallRequest as CRequest;
|
use v1::helpers::{CallRequest as CRequest, errors};
|
||||||
use v1::impls::{default_gas_price, dispatch_transaction, error_codes, from_params_default_second, from_params_default_third};
|
use v1::helpers::dispatch::{default_gas_price, dispatch_transaction};
|
||||||
|
use v1::helpers::params::{expect_no_params, from_params_default_second, from_params_default_third};
|
||||||
|
|
||||||
/// Eth RPC options
|
/// Eth RPC options
|
||||||
pub struct EthClientOptions {
|
pub struct EthClientOptions {
|
||||||
@ -214,30 +215,6 @@ pub fn pending_logs<M>(miner: &M, filter: &EthcoreFilter) -> Vec<Log> where M: M
|
|||||||
|
|
||||||
const MAX_QUEUE_SIZE_TO_MINE_ON: usize = 4; // because uncles go back 6.
|
const MAX_QUEUE_SIZE_TO_MINE_ON: usize = 4; // because uncles go back 6.
|
||||||
|
|
||||||
fn make_unsupported_err() -> Error {
|
|
||||||
Error {
|
|
||||||
code: ErrorCode::ServerError(error_codes::UNSUPPORTED_REQUEST_CODE),
|
|
||||||
message: "Unsupported request.".into(),
|
|
||||||
data: None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn no_work_err() -> Error {
|
|
||||||
Error {
|
|
||||||
code: ErrorCode::ServerError(error_codes::NO_WORK_CODE),
|
|
||||||
message: "Still syncing.".into(),
|
|
||||||
data: None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn no_author_err() -> Error {
|
|
||||||
Error {
|
|
||||||
code: ErrorCode::ServerError(error_codes::NO_AUTHOR_CODE),
|
|
||||||
message: "Author not configured. Run parity with --author to configure.".into(),
|
|
||||||
data: None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C, S: ?Sized, M, EM> EthClient<C, S, M, EM> where
|
impl<C, S: ?Sized, M, EM> EthClient<C, S, M, EM> where
|
||||||
C: MiningBlockChainClient + 'static,
|
C: MiningBlockChainClient + 'static,
|
||||||
S: SyncProvider + 'static,
|
S: SyncProvider + 'static,
|
||||||
@ -265,16 +242,15 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
|
|||||||
|
|
||||||
fn protocol_version(&self, params: Params) -> Result<Value, Error> {
|
fn protocol_version(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
match params {
|
try!(expect_no_params(params));
|
||||||
Params::None => Ok(Value::String(format!("{}", take_weak!(self.sync).status().protocol_version).to_owned())),
|
|
||||||
_ => Err(Error::invalid_params())
|
Ok(Value::String(format!("{}", take_weak!(self.sync).status().protocol_version).to_owned()))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn syncing(&self, params: Params) -> Result<Value, Error> {
|
fn syncing(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
match params {
|
try!(expect_no_params(params));
|
||||||
Params::None => {
|
|
||||||
let status = take_weak!(self.sync).status();
|
let status = take_weak!(self.sync).status();
|
||||||
let res = match status.state {
|
let res = match status.state {
|
||||||
SyncState::Idle => SyncStatus::None,
|
SyncState::Idle => SyncStatus::None,
|
||||||
@ -296,63 +272,50 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
|
|||||||
};
|
};
|
||||||
to_value(&res)
|
to_value(&res)
|
||||||
}
|
}
|
||||||
_ => Err(Error::invalid_params()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn author(&self, params: Params) -> Result<Value, Error> {
|
fn author(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
match params {
|
try!(expect_no_params(params));
|
||||||
Params::None => to_value(&RpcH160::from(take_weak!(self.miner).author())),
|
|
||||||
_ => Err(Error::invalid_params()),
|
to_value(&RpcH160::from(take_weak!(self.miner).author()))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_mining(&self, params: Params) -> Result<Value, Error> {
|
fn is_mining(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
match params {
|
try!(expect_no_params(params));
|
||||||
Params::None => to_value(&(take_weak!(self.miner).is_sealing())),
|
|
||||||
_ => Err(Error::invalid_params())
|
to_value(&(take_weak!(self.miner).is_sealing()))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hashrate(&self, params: Params) -> Result<Value, Error> {
|
fn hashrate(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
match params {
|
try!(expect_no_params(params));
|
||||||
Params::None => to_value(&RpcU256::from(self.external_miner.hashrate())),
|
|
||||||
_ => Err(Error::invalid_params())
|
to_value(&RpcU256::from(self.external_miner.hashrate()))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gas_price(&self, params: Params) -> Result<Value, Error> {
|
fn gas_price(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
match params {
|
try!(expect_no_params(params));
|
||||||
Params::None => {
|
|
||||||
let (client, miner) = (take_weak!(self.client), take_weak!(self.miner));
|
let (client, miner) = (take_weak!(self.client), take_weak!(self.miner));
|
||||||
to_value(&RpcU256::from(default_gas_price(&*client, &*miner)))
|
to_value(&RpcU256::from(default_gas_price(&*client, &*miner)))
|
||||||
}
|
}
|
||||||
_ => Err(Error::invalid_params())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn accounts(&self, params: Params) -> Result<Value, Error> {
|
fn accounts(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
match params {
|
try!(expect_no_params(params));
|
||||||
Params::None => {
|
|
||||||
let store = take_weak!(self.accounts);
|
let store = take_weak!(self.accounts);
|
||||||
let accounts = try!(store.accounts().map_err(|_| Error::internal_error()));
|
let accounts = try!(store.accounts().map_err(|e| errors::internal("Could not fetch accounts.", e)));
|
||||||
to_value(&accounts.into_iter().map(Into::into).collect::<Vec<RpcH160>>())
|
to_value(&accounts.into_iter().map(Into::into).collect::<Vec<RpcH160>>())
|
||||||
},
|
|
||||||
_ => Err(Error::invalid_params())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_number(&self, params: Params) -> Result<Value, Error> {
|
fn block_number(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
match params {
|
try!(expect_no_params(params));
|
||||||
Params::None => to_value(&RpcU256::from(take_weak!(self.client).chain_info().best_block_number)),
|
|
||||||
_ => Err(Error::invalid_params())
|
to_value(&RpcU256::from(take_weak!(self.client).chain_info().best_block_number))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn balance(&self, params: Params) -> Result<Value, Error> {
|
fn balance(&self, params: Params) -> Result<Value, Error> {
|
||||||
@ -362,7 +325,10 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
|
|||||||
let address: Address = RpcH160::into(address);
|
let address: Address = RpcH160::into(address);
|
||||||
match block_number {
|
match block_number {
|
||||||
BlockNumber::Pending => to_value(&RpcU256::from(take_weak!(self.miner).balance(take_weak!(self.client).deref(), &address))),
|
BlockNumber::Pending => to_value(&RpcU256::from(take_weak!(self.miner).balance(take_weak!(self.client).deref(), &address))),
|
||||||
id => to_value(&RpcU256::from(try!(take_weak!(self.client).balance(&address, id.into()).ok_or_else(make_unsupported_err)))),
|
id => match take_weak!(self.client).balance(&address, id.into()) {
|
||||||
|
Some(balance) => to_value(&RpcU256::from(balance)),
|
||||||
|
None => Err(errors::state_pruned()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -377,7 +343,7 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
|
|||||||
BlockNumber::Pending => to_value(&RpcU256::from(take_weak!(self.miner).storage_at(&*take_weak!(self.client), &address, &H256::from(position)))),
|
BlockNumber::Pending => to_value(&RpcU256::from(take_weak!(self.miner).storage_at(&*take_weak!(self.client), &address, &H256::from(position)))),
|
||||||
id => match take_weak!(self.client).storage_at(&address, &H256::from(position), id.into()) {
|
id => match take_weak!(self.client).storage_at(&address, &H256::from(position), id.into()) {
|
||||||
Some(s) => to_value(&RpcH256::from(s)),
|
Some(s) => to_value(&RpcH256::from(s)),
|
||||||
None => Err(make_unsupported_err()), // None is only returned on unsupported requests.
|
None => Err(errors::state_pruned()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -391,7 +357,10 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
|
|||||||
let address: Address = RpcH160::into(address);
|
let address: Address = RpcH160::into(address);
|
||||||
match block_number {
|
match block_number {
|
||||||
BlockNumber::Pending => to_value(&RpcU256::from(take_weak!(self.miner).nonce(take_weak!(self.client).deref(), &address))),
|
BlockNumber::Pending => to_value(&RpcU256::from(take_weak!(self.miner).nonce(take_weak!(self.client).deref(), &address))),
|
||||||
id => to_value(&take_weak!(self.client).nonce(&address, id.into()).map(RpcU256::from)),
|
id => match take_weak!(self.client).nonce(&address, id.into()) {
|
||||||
|
Some(nonce) => to_value(&RpcU256::from(nonce)),
|
||||||
|
None => Err(errors::state_pruned()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -441,8 +410,10 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
|
|||||||
let address: Address = RpcH160::into(address);
|
let address: Address = RpcH160::into(address);
|
||||||
match block_number {
|
match block_number {
|
||||||
BlockNumber::Pending => to_value(&take_weak!(self.miner).code(take_weak!(self.client).deref(), &address).map_or_else(Bytes::default, Bytes::new)),
|
BlockNumber::Pending => to_value(&take_weak!(self.miner).code(take_weak!(self.client).deref(), &address).map_or_else(Bytes::default, Bytes::new)),
|
||||||
BlockNumber::Latest => to_value(&take_weak!(self.client).code(&address).map_or_else(Bytes::default, Bytes::new)),
|
_ => match take_weak!(self.client).code(&address, block_number.into()) {
|
||||||
_ => Err(Error::invalid_params()),
|
Some(code) => to_value(&code.map_or_else(Bytes::default, Bytes::new)),
|
||||||
|
None => Err(errors::state_pruned()),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -515,17 +486,14 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
|
|||||||
|
|
||||||
fn compilers(&self, params: Params) -> Result<Value, Error> {
|
fn compilers(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
match params {
|
try!(expect_no_params(params));
|
||||||
Params::None => {
|
|
||||||
let mut compilers = vec![];
|
let mut compilers = vec![];
|
||||||
if Command::new(SOLC).output().is_ok() {
|
if Command::new(SOLC).output().is_ok() {
|
||||||
compilers.push("solidity".to_owned())
|
compilers.push("solidity".to_owned())
|
||||||
}
|
}
|
||||||
to_value(&compilers)
|
to_value(&compilers)
|
||||||
}
|
}
|
||||||
_ => Err(Error::invalid_params())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn logs(&self, params: Params) -> Result<Value, Error> {
|
fn logs(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
@ -549,8 +517,8 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
|
|||||||
|
|
||||||
fn work(&self, params: Params) -> Result<Value, Error> {
|
fn work(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
match params {
|
try!(expect_no_params(params));
|
||||||
Params::None => {
|
|
||||||
let client = take_weak!(self.client);
|
let client = take_weak!(self.client);
|
||||||
// check if we're still syncing and return empty strings in that case
|
// check if we're still syncing and return empty strings in that case
|
||||||
{
|
{
|
||||||
@ -558,7 +526,7 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
|
|||||||
//let sync = take_weak!(self.sync);
|
//let sync = take_weak!(self.sync);
|
||||||
if /*sync.status().state != SyncState::Idle ||*/ client.queue_info().total_queue_size() > MAX_QUEUE_SIZE_TO_MINE_ON {
|
if /*sync.status().state != SyncState::Idle ||*/ client.queue_info().total_queue_size() > MAX_QUEUE_SIZE_TO_MINE_ON {
|
||||||
trace!(target: "miner", "Syncing. Cannot give any work.");
|
trace!(target: "miner", "Syncing. Cannot give any work.");
|
||||||
return Err(no_work_err());
|
return Err(errors::no_work());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise spin until our submitted block has been included.
|
// Otherwise spin until our submitted block has been included.
|
||||||
@ -571,7 +539,7 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
|
|||||||
let miner = take_weak!(self.miner);
|
let miner = take_weak!(self.miner);
|
||||||
if miner.author().is_zero() {
|
if miner.author().is_zero() {
|
||||||
warn!(target: "miner", "Cannot give work package - no author is configured. Use --author to configure!");
|
warn!(target: "miner", "Cannot give work package - no author is configured. Use --author to configure!");
|
||||||
return Err(no_author_err())
|
return Err(errors::no_author())
|
||||||
}
|
}
|
||||||
miner.map_sealing_work(client.deref(), |b| {
|
miner.map_sealing_work(client.deref(), |b| {
|
||||||
let pow_hash = b.hash();
|
let pow_hash = b.hash();
|
||||||
@ -585,9 +553,6 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
|
|||||||
to_value(&(RpcH256::from(pow_hash), RpcH256::from(seed_hash), RpcH256::from(target)))
|
to_value(&(RpcH256::from(pow_hash), RpcH256::from(seed_hash), RpcH256::from(target)))
|
||||||
}
|
}
|
||||||
}).unwrap_or(Err(Error::internal_error())) // no work found.
|
}).unwrap_or(Err(Error::internal_error())) // no work found.
|
||||||
},
|
|
||||||
_ => Err(Error::invalid_params())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn submit_work(&self, params: Params) -> Result<Value, Error> {
|
fn submit_work(&self, params: Params) -> Result<Value, Error> {
|
||||||
@ -627,7 +592,6 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
|
|||||||
|
|
||||||
fn call(&self, params: Params) -> Result<Value, Error> {
|
fn call(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
trace!(target: "jsonrpc", "call: {:?}", params);
|
|
||||||
from_params_default_second(params)
|
from_params_default_second(params)
|
||||||
.and_then(|(request, block_number,)| {
|
.and_then(|(request, block_number,)| {
|
||||||
let request = CallRequest::into(request);
|
let request = CallRequest::into(request);
|
||||||
@ -675,17 +639,23 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
|
|||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.stderr(Stdio::null())
|
.stderr(Stdio::null())
|
||||||
.spawn();
|
.spawn();
|
||||||
if let Ok(mut child) = maybe_child {
|
|
||||||
if let Ok(_) = child.stdin.as_mut().expect("we called child.stdin(Stdio::piped()) before spawn; qed").write_all(code.as_bytes()) {
|
maybe_child
|
||||||
if let Ok(output) = child.wait_with_output() {
|
.map_err(errors::compilation)
|
||||||
|
.and_then(|mut child| {
|
||||||
|
try!(child.stdin.as_mut()
|
||||||
|
.expect("we called child.stdin(Stdio::piped()) before spawn; qed")
|
||||||
|
.write_all(code.as_bytes())
|
||||||
|
.map_err(errors::compilation));
|
||||||
|
let output = try!(child.wait_with_output().map_err(errors::compilation));
|
||||||
|
|
||||||
let s = String::from_utf8_lossy(&output.stdout);
|
let s = String::from_utf8_lossy(&output.stdout);
|
||||||
if let Some(hex) = s.lines().skip_while(|ref l| !l.contains("Binary")).skip(1).next() {
|
if let Some(hex) = s.lines().skip_while(|ref l| !l.contains("Binary")).skip(1).next() {
|
||||||
return to_value(&Bytes::new(hex.from_hex().unwrap_or(vec![])));
|
to_value(&Bytes::new(hex.from_hex().unwrap_or(vec![])))
|
||||||
|
} else {
|
||||||
|
Err(errors::compilation("Unexpected output."))
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(Error::invalid_params())
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ use util::Mutex;
|
|||||||
use v1::traits::EthFilter;
|
use v1::traits::EthFilter;
|
||||||
use v1::types::{BlockNumber, Index, Filter, Log, H256 as RpcH256, U256 as RpcU256};
|
use v1::types::{BlockNumber, Index, Filter, Log, H256 as RpcH256, U256 as RpcU256};
|
||||||
use v1::helpers::{PollFilter, PollManager};
|
use v1::helpers::{PollFilter, PollManager};
|
||||||
|
use v1::helpers::params::expect_no_params;
|
||||||
use v1::impls::eth::pending_logs;
|
use v1::impls::eth::pending_logs;
|
||||||
|
|
||||||
/// Eth filter rpc implementation.
|
/// Eth filter rpc implementation.
|
||||||
@ -76,28 +77,22 @@ impl<C, M> EthFilter for EthFilterClient<C, M> where
|
|||||||
|
|
||||||
fn new_block_filter(&self, params: Params) -> Result<Value, Error> {
|
fn new_block_filter(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
match params {
|
try!(expect_no_params(params));
|
||||||
Params::None => {
|
|
||||||
let mut polls = self.polls.lock();
|
let mut polls = self.polls.lock();
|
||||||
let id = polls.create_poll(PollFilter::Block(take_weak!(self.client).chain_info().best_block_number));
|
let id = polls.create_poll(PollFilter::Block(take_weak!(self.client).chain_info().best_block_number));
|
||||||
to_value(&RpcU256::from(id))
|
to_value(&RpcU256::from(id))
|
||||||
},
|
|
||||||
_ => Err(Error::invalid_params())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_pending_transaction_filter(&self, params: Params) -> Result<Value, Error> {
|
fn new_pending_transaction_filter(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
match params {
|
try!(expect_no_params(params));
|
||||||
Params::None => {
|
|
||||||
let mut polls = self.polls.lock();
|
let mut polls = self.polls.lock();
|
||||||
let pending_transactions = take_weak!(self.miner).pending_transactions_hashes();
|
let pending_transactions = take_weak!(self.miner).pending_transactions_hashes();
|
||||||
let id = polls.create_poll(PollFilter::PendingTransaction(pending_transactions));
|
let id = polls.create_poll(PollFilter::PendingTransaction(pending_transactions));
|
||||||
|
|
||||||
to_value(&RpcU256::from(id))
|
to_value(&RpcU256::from(id))
|
||||||
},
|
|
||||||
_ => Err(Error::invalid_params())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filter_changes(&self, params: Params) -> Result<Value, Error> {
|
fn filter_changes(&self, params: Params) -> Result<Value, Error> {
|
||||||
|
@ -23,10 +23,10 @@ use ethcore::client::MiningBlockChainClient;
|
|||||||
use util::{U256, Address, H256, Mutex};
|
use util::{U256, Address, H256, Mutex};
|
||||||
use transient_hashmap::TransientHashMap;
|
use transient_hashmap::TransientHashMap;
|
||||||
use ethcore::account_provider::AccountProvider;
|
use ethcore::account_provider::AccountProvider;
|
||||||
use v1::helpers::{SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationsQueue, ConfirmationPayload, TransactionRequest as TRequest, FilledTransactionRequest as FilledRequest};
|
use v1::helpers::{errors, SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationsQueue, ConfirmationPayload, TransactionRequest as TRequest, FilledTransactionRequest as FilledRequest};
|
||||||
|
use v1::helpers::dispatch::{default_gas_price, sign_and_dispatch};
|
||||||
use v1::traits::EthSigning;
|
use v1::traits::EthSigning;
|
||||||
use v1::types::{TransactionRequest, H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, U256 as RpcU256};
|
use v1::types::{TransactionRequest, H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, U256 as RpcU256};
|
||||||
use v1::impls::{default_gas_price, sign_and_dispatch, request_rejected_error, request_not_found_error, signer_disabled_error};
|
|
||||||
|
|
||||||
fn fill_optional_fields<C, M>(request: TRequest, client: &C, miner: &M) -> FilledRequest
|
fn fill_optional_fields<C, M>(request: TRequest, client: &C, miner: &M) -> FilledRequest
|
||||||
where C: MiningBlockChainClient, M: MinerService {
|
where C: MiningBlockChainClient, M: MinerService {
|
||||||
@ -151,10 +151,10 @@ impl<C, M> EthSigning for EthSigningQueueClient<C, M>
|
|||||||
let res = match pending.get(&id) {
|
let res = match pending.get(&id) {
|
||||||
Some(ref promise) => match promise.result() {
|
Some(ref promise) => match promise.result() {
|
||||||
ConfirmationResult::Waiting => { return Ok(Value::Null); }
|
ConfirmationResult::Waiting => { return Ok(Value::Null); }
|
||||||
ConfirmationResult::Rejected => Err(request_rejected_error()),
|
ConfirmationResult::Rejected => Err(errors::request_rejected()),
|
||||||
ConfirmationResult::Confirmed(rpc_response) => rpc_response,
|
ConfirmationResult::Confirmed(rpc_response) => rpc_response,
|
||||||
},
|
},
|
||||||
_ => { return Err(request_not_found_error()); }
|
_ => { return Err(errors::request_not_found()); }
|
||||||
};
|
};
|
||||||
pending.remove(&id);
|
pending.remove(&id);
|
||||||
res
|
res
|
||||||
@ -217,16 +217,16 @@ impl<C, M> EthSigning for EthSigningUnsafeClient<C, M> where
|
|||||||
|
|
||||||
fn post_sign(&self, _: Params) -> Result<Value, Error> {
|
fn post_sign(&self, _: Params) -> Result<Value, Error> {
|
||||||
// We don't support this in non-signer mode.
|
// We don't support this in non-signer mode.
|
||||||
Err(signer_disabled_error())
|
Err(errors::signer_disabled())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn post_transaction(&self, _: Params) -> Result<Value, Error> {
|
fn post_transaction(&self, _: Params) -> Result<Value, Error> {
|
||||||
// We don't support this in non-signer mode.
|
// We don't support this in non-signer mode.
|
||||||
Err(signer_disabled_error())
|
Err(errors::signer_disabled())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_request(&self, _: Params) -> Result<Value, Error> {
|
fn check_request(&self, _: Params) -> Result<Value, Error> {
|
||||||
// We don't support this in non-signer mode.
|
// We don't support this in non-signer mode.
|
||||||
Err(signer_disabled_error())
|
Err(errors::signer_disabled())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,8 @@ use jsonrpc_core::*;
|
|||||||
use ethcore::miner::MinerService;
|
use ethcore::miner::MinerService;
|
||||||
use v1::traits::Ethcore;
|
use v1::traits::Ethcore;
|
||||||
use v1::types::{Bytes, U256};
|
use v1::types::{Bytes, U256};
|
||||||
use v1::helpers::{SigningQueue, ConfirmationsQueue, NetworkSettings};
|
use v1::helpers::{errors, SigningQueue, ConfirmationsQueue, NetworkSettings};
|
||||||
use v1::impls::signer_disabled_error;
|
use v1::helpers::params::expect_no_params;
|
||||||
|
|
||||||
/// Ethcore implementation.
|
/// Ethcore implementation.
|
||||||
pub struct EthcoreClient<C, M> where
|
pub struct EthcoreClient<C, M> where
|
||||||
@ -61,64 +61,76 @@ impl<C, M> EthcoreClient<C, M> where C: MiningBlockChainClient, M: MinerService
|
|||||||
|
|
||||||
impl<C, M> Ethcore for EthcoreClient<C, M> where M: MinerService + 'static, C: MiningBlockChainClient + 'static {
|
impl<C, M> Ethcore for EthcoreClient<C, M> where M: MinerService + 'static, C: MiningBlockChainClient + 'static {
|
||||||
|
|
||||||
fn transactions_limit(&self, _: Params) -> Result<Value, Error> {
|
fn transactions_limit(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
|
try!(expect_no_params(params));
|
||||||
to_value(&take_weak!(self.miner).transactions_limit())
|
to_value(&take_weak!(self.miner).transactions_limit())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn min_gas_price(&self, _: Params) -> Result<Value, Error> {
|
fn min_gas_price(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
|
try!(expect_no_params(params));
|
||||||
to_value(&U256::from(take_weak!(self.miner).minimal_gas_price()))
|
to_value(&U256::from(take_weak!(self.miner).minimal_gas_price()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extra_data(&self, _: Params) -> Result<Value, Error> {
|
fn extra_data(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
|
try!(expect_no_params(params));
|
||||||
to_value(&Bytes::new(take_weak!(self.miner).extra_data()))
|
to_value(&Bytes::new(take_weak!(self.miner).extra_data()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gas_floor_target(&self, _: Params) -> Result<Value, Error> {
|
fn gas_floor_target(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
|
try!(expect_no_params(params));
|
||||||
to_value(&U256::from(take_weak!(self.miner).gas_floor_target()))
|
to_value(&U256::from(take_weak!(self.miner).gas_floor_target()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gas_ceil_target(&self, _: Params) -> Result<Value, Error> {
|
fn gas_ceil_target(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
|
try!(expect_no_params(params));
|
||||||
to_value(&U256::from(take_weak!(self.miner).gas_ceil_target()))
|
to_value(&U256::from(take_weak!(self.miner).gas_ceil_target()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dev_logs(&self, _params: Params) -> Result<Value, Error> {
|
fn dev_logs(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
|
try!(expect_no_params(params));
|
||||||
let logs = self.logger.logs();
|
let logs = self.logger.logs();
|
||||||
to_value(&logs.deref().as_slice())
|
to_value(&logs.deref().as_slice())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dev_logs_levels(&self, _params: Params) -> Result<Value, Error> {
|
fn dev_logs_levels(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
|
try!(expect_no_params(params));
|
||||||
to_value(&self.logger.levels())
|
to_value(&self.logger.levels())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn net_chain(&self, _params: Params) -> Result<Value, Error> {
|
fn net_chain(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
|
try!(expect_no_params(params));
|
||||||
to_value(&self.settings.chain)
|
to_value(&self.settings.chain)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn net_max_peers(&self, _params: Params) -> Result<Value, Error> {
|
fn net_max_peers(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
|
try!(expect_no_params(params));
|
||||||
to_value(&self.settings.max_peers)
|
to_value(&self.settings.max_peers)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn net_port(&self, _params: Params) -> Result<Value, Error> {
|
fn net_port(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
|
try!(expect_no_params(params));
|
||||||
to_value(&self.settings.network_port)
|
to_value(&self.settings.network_port)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn node_name(&self, _params: Params) -> Result<Value, Error> {
|
fn node_name(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
|
try!(expect_no_params(params));
|
||||||
to_value(&self.settings.name)
|
to_value(&self.settings.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rpc_settings(&self, _params: Params) -> Result<Value, Error> {
|
fn rpc_settings(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
|
try!(expect_no_params(params));
|
||||||
let mut map = BTreeMap::new();
|
let mut map = BTreeMap::new();
|
||||||
map.insert("enabled".to_owned(), Value::Bool(self.settings.rpc_enabled));
|
map.insert("enabled".to_owned(), Value::Bool(self.settings.rpc_enabled));
|
||||||
map.insert("interface".to_owned(), Value::String(self.settings.rpc_interface.clone()));
|
map.insert("interface".to_owned(), Value::String(self.settings.rpc_interface.clone()));
|
||||||
@ -128,30 +140,29 @@ impl<C, M> Ethcore for EthcoreClient<C, M> where M: MinerService + 'static, C: M
|
|||||||
|
|
||||||
fn default_extra_data(&self, params: Params) -> Result<Value, Error> {
|
fn default_extra_data(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
match params {
|
try!(expect_no_params(params));
|
||||||
Params::None => to_value(&Bytes::new(version_data())),
|
to_value(&Bytes::new(version_data()))
|
||||||
_ => Err(Error::invalid_params()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gas_price_statistics(&self, params: Params) -> Result<Value, Error> {
|
fn gas_price_statistics(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
match params {
|
try!(expect_no_params(params));
|
||||||
Params::None => match take_weak!(self.client).gas_price_statistics(100, 8) {
|
|
||||||
|
match take_weak!(self.client).gas_price_statistics(100, 8) {
|
||||||
Ok(stats) => to_value(&stats
|
Ok(stats) => to_value(&stats
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|x| to_value(&U256::from(x)).expect("x must be U256; qed"))
|
.map(|x| to_value(&U256::from(x)).expect("x must be U256; qed"))
|
||||||
.collect::<Vec<_>>()),
|
.collect::<Vec<_>>()),
|
||||||
_ => Err(Error::internal_error()),
|
_ => Err(Error::internal_error()),
|
||||||
},
|
|
||||||
_ => Err(Error::invalid_params()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unsigned_transactions_count(&self, _params: Params) -> Result<Value, Error> {
|
fn unsigned_transactions_count(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
|
try!(expect_no_params(params));
|
||||||
|
|
||||||
match self.confirmations_queue {
|
match self.confirmations_queue {
|
||||||
None => Err(signer_disabled_error()),
|
None => Err(errors::signer_disabled()),
|
||||||
Some(ref queue) => to_value(&queue.len()),
|
Some(ref queue) => to_value(&queue.len()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@ use jsonrpc_core::*;
|
|||||||
use ethcore::miner::MinerService;
|
use ethcore::miner::MinerService;
|
||||||
use ethcore::client::MiningBlockChainClient;
|
use ethcore::client::MiningBlockChainClient;
|
||||||
use ethsync::ManageNetwork;
|
use ethsync::ManageNetwork;
|
||||||
|
use v1::helpers::errors;
|
||||||
|
use v1::helpers::params::expect_no_params;
|
||||||
use v1::traits::EthcoreSet;
|
use v1::traits::EthcoreSet;
|
||||||
use v1::types::{Bytes, H160, U256};
|
use v1::types::{Bytes, H160, U256};
|
||||||
|
|
||||||
@ -117,7 +119,7 @@ impl<C, M> EthcoreSet for EthcoreSetClient<C, M> where
|
|||||||
from_params::<(String,)>(params).and_then(|(peer,)| {
|
from_params::<(String,)>(params).and_then(|(peer,)| {
|
||||||
match take_weak!(self.net).add_reserved_peer(peer) {
|
match take_weak!(self.net).add_reserved_peer(peer) {
|
||||||
Ok(()) => to_value(&true),
|
Ok(()) => to_value(&true),
|
||||||
Err(_) => Err(Error::invalid_params()),
|
Err(e) => Err(errors::invalid_params("Peer address", e)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -127,29 +129,33 @@ impl<C, M> EthcoreSet for EthcoreSetClient<C, M> where
|
|||||||
from_params::<(String,)>(params).and_then(|(peer,)| {
|
from_params::<(String,)>(params).and_then(|(peer,)| {
|
||||||
match take_weak!(self.net).remove_reserved_peer(peer) {
|
match take_weak!(self.net).remove_reserved_peer(peer) {
|
||||||
Ok(()) => to_value(&true),
|
Ok(()) => to_value(&true),
|
||||||
Err(_) => Err(Error::invalid_params()),
|
Err(e) => Err(errors::invalid_params("Peer address", e)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn drop_non_reserved_peers(&self, _: Params) -> Result<Value, Error> {
|
fn drop_non_reserved_peers(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
|
try!(expect_no_params(params));
|
||||||
take_weak!(self.net).deny_unreserved_peers();
|
take_weak!(self.net).deny_unreserved_peers();
|
||||||
to_value(&true)
|
to_value(&true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn accept_non_reserved_peers(&self, _: Params) -> Result<Value, Error> {
|
fn accept_non_reserved_peers(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
|
try!(expect_no_params(params));
|
||||||
take_weak!(self.net).accept_unreserved_peers();
|
take_weak!(self.net).accept_unreserved_peers();
|
||||||
to_value(&true)
|
to_value(&true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_network(&self, _: Params) -> Result<Value, Error> {
|
fn start_network(&self, params: Params) -> Result<Value, Error> {
|
||||||
|
try!(expect_no_params(params));
|
||||||
take_weak!(self.net).start_network();
|
take_weak!(self.net).start_network();
|
||||||
Ok(Value::Bool(true))
|
Ok(Value::Bool(true))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stop_network(&self, _: Params) -> Result<Value, Error> {
|
fn stop_network(&self, params: Params) -> Result<Value, Error> {
|
||||||
|
try!(expect_no_params(params));
|
||||||
take_weak!(self.net).stop_network();
|
take_weak!(self.net).stop_network();
|
||||||
Ok(Value::Bool(true))
|
Ok(Value::Bool(true))
|
||||||
}
|
}
|
||||||
|
@ -25,21 +25,17 @@ macro_rules! take_weak {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! rpc_unimplemented {
|
|
||||||
() => (Err(Error::internal_error()))
|
|
||||||
}
|
|
||||||
|
|
||||||
mod web3;
|
|
||||||
mod eth;
|
mod eth;
|
||||||
mod eth_filter;
|
mod eth_filter;
|
||||||
mod eth_signing;
|
mod eth_signing;
|
||||||
|
mod ethcore;
|
||||||
|
mod ethcore_set;
|
||||||
mod net;
|
mod net;
|
||||||
mod personal;
|
mod personal;
|
||||||
mod personal_signer;
|
mod personal_signer;
|
||||||
mod ethcore;
|
|
||||||
mod ethcore_set;
|
|
||||||
mod traces;
|
|
||||||
mod rpc;
|
mod rpc;
|
||||||
|
mod traces;
|
||||||
|
mod web3;
|
||||||
|
|
||||||
pub use self::web3::Web3Client;
|
pub use self::web3::Web3Client;
|
||||||
pub use self::eth::{EthClient, EthClientOptions};
|
pub use self::eth::{EthClient, EthClientOptions};
|
||||||
@ -52,203 +48,3 @@ pub use self::ethcore::EthcoreClient;
|
|||||||
pub use self::ethcore_set::EthcoreSetClient;
|
pub use self::ethcore_set::EthcoreSetClient;
|
||||||
pub use self::traces::TracesClient;
|
pub use self::traces::TracesClient;
|
||||||
pub use self::rpc::RpcClient;
|
pub use self::rpc::RpcClient;
|
||||||
|
|
||||||
use serde;
|
|
||||||
use v1::helpers::TransactionRequest;
|
|
||||||
use v1::types::{H256 as RpcH256, H520 as RpcH520, BlockNumber};
|
|
||||||
use ethcore::error::Error as EthcoreError;
|
|
||||||
use ethcore::miner::MinerService;
|
|
||||||
use ethcore::client::MiningBlockChainClient;
|
|
||||||
use ethcore::transaction::{Action, SignedTransaction, Transaction};
|
|
||||||
use ethcore::account_provider::{AccountProvider, Error as AccountError};
|
|
||||||
use util::{U256, H256, Address};
|
|
||||||
use util::rlp::encode;
|
|
||||||
use util::bytes::ToPretty;
|
|
||||||
use jsonrpc_core::{Error, ErrorCode, Value, to_value, from_params, Params};
|
|
||||||
|
|
||||||
mod error_codes {
|
|
||||||
// NOTE [ToDr] Codes from [-32099, -32000]
|
|
||||||
pub const UNSUPPORTED_REQUEST_CODE: i64 = -32000;
|
|
||||||
pub const NO_WORK_CODE: i64 = -32001;
|
|
||||||
pub const NO_AUTHOR_CODE: i64 = -32002;
|
|
||||||
pub const UNKNOWN_ERROR: i64 = -32009;
|
|
||||||
pub const TRANSACTION_ERROR: i64 = -32010;
|
|
||||||
pub const ACCOUNT_LOCKED: i64 = -32020;
|
|
||||||
pub const PASSWORD_INVALID: i64 = -32021;
|
|
||||||
pub const SIGNER_DISABLED: i64 = -32030;
|
|
||||||
pub const REQUEST_REJECTED: i64 = -32040;
|
|
||||||
pub const REQUEST_NOT_FOUND: i64 = -32041;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn params_len(params: &Params) -> usize {
|
|
||||||
match params {
|
|
||||||
&Params::Array(ref vec) => vec.len(),
|
|
||||||
_ => 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserialize request parameters with optional second parameter `BlockNumber` defaulting to `BlockNumber::Latest`.
|
|
||||||
pub fn from_params_default_second<F>(params: Params) -> Result<(F, BlockNumber, ), Error> where F: serde::de::Deserialize {
|
|
||||||
match params_len(¶ms) {
|
|
||||||
1 => from_params::<(F, )>(params).map(|(f,)| (f, BlockNumber::Latest)),
|
|
||||||
_ => from_params::<(F, BlockNumber)>(params),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserialize request parameters with optional third parameter `BlockNumber` defaulting to `BlockNumber::Latest`.
|
|
||||||
pub fn from_params_default_third<F1, F2>(params: Params) -> Result<(F1, F2, BlockNumber, ), Error> where F1: serde::de::Deserialize, F2: serde::de::Deserialize {
|
|
||||||
match params_len(¶ms) {
|
|
||||||
2 => from_params::<(F1, F2, )>(params).map(|(f1, f2)| (f1, f2, BlockNumber::Latest)),
|
|
||||||
_ => from_params::<(F1, F2, BlockNumber)>(params)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn dispatch_transaction<C, M>(client: &C, miner: &M, signed_transaction: SignedTransaction) -> Result<Value, Error>
|
|
||||||
where C: MiningBlockChainClient, M: MinerService {
|
|
||||||
let hash = RpcH256::from(signed_transaction.hash());
|
|
||||||
|
|
||||||
let import = miner.import_own_transaction(client, signed_transaction);
|
|
||||||
|
|
||||||
import
|
|
||||||
.map_err(transaction_error)
|
|
||||||
.and_then(|_| to_value(&hash))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn signature_with_password(accounts: &AccountProvider, address: Address, hash: H256, pass: String) -> Result<Value, Error> {
|
|
||||||
accounts.sign_with_password(address, pass, hash)
|
|
||||||
.map_err(password_error)
|
|
||||||
.and_then(|hash| to_value(&RpcH520::from(hash)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prepare_transaction<C, M>(client: &C, miner: &M, request: TransactionRequest) -> Transaction where C: MiningBlockChainClient, M: MinerService {
|
|
||||||
Transaction {
|
|
||||||
nonce: request.nonce
|
|
||||||
.or_else(|| miner
|
|
||||||
.last_nonce(&request.from)
|
|
||||||
.map(|nonce| nonce + 1.into()))
|
|
||||||
.unwrap_or_else(|| client.latest_nonce(&request.from)),
|
|
||||||
|
|
||||||
action: request.to.map_or(Action::Create, Action::Call),
|
|
||||||
gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()),
|
|
||||||
gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(client, miner)),
|
|
||||||
value: request.value.unwrap_or_else(U256::default),
|
|
||||||
data: request.data.map_or_else(Vec::new, |b| b.to_vec()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unlock_sign_and_dispatch<C, M>(client: &C, miner: &M, request: TransactionRequest, account_provider: &AccountProvider, password: String) -> Result<Value, Error>
|
|
||||||
where C: MiningBlockChainClient, M: MinerService {
|
|
||||||
|
|
||||||
let address = request.from;
|
|
||||||
let signed_transaction = {
|
|
||||||
let t = prepare_transaction(client, miner, request);
|
|
||||||
let hash = t.hash();
|
|
||||||
let signature = try!(account_provider.sign_with_password(address, password, hash).map_err(password_error));
|
|
||||||
t.with_signature(signature)
|
|
||||||
};
|
|
||||||
|
|
||||||
trace!(target: "miner", "send_transaction: dispatching tx: {}", encode(&signed_transaction).to_vec().pretty());
|
|
||||||
dispatch_transaction(&*client, &*miner, signed_transaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sign_and_dispatch<C, M>(client: &C, miner: &M, request: TransactionRequest, account_provider: &AccountProvider, address: Address) -> Result<Value, Error>
|
|
||||||
where C: MiningBlockChainClient, M: MinerService {
|
|
||||||
|
|
||||||
let signed_transaction = {
|
|
||||||
let t = prepare_transaction(client, miner, request);
|
|
||||||
let hash = t.hash();
|
|
||||||
let signature = try!(account_provider.sign(address, hash).map_err(signing_error));
|
|
||||||
t.with_signature(signature)
|
|
||||||
};
|
|
||||||
|
|
||||||
trace!(target: "miner", "send_transaction: dispatching tx: {}", encode(&signed_transaction).to_vec().pretty());
|
|
||||||
dispatch_transaction(&*client, &*miner, signed_transaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_gas_price<C, M>(client: &C, miner: &M) -> U256 where C: MiningBlockChainClient, M: MinerService {
|
|
||||||
client
|
|
||||||
.gas_price_statistics(100, 8)
|
|
||||||
.map(|x| x[4])
|
|
||||||
.unwrap_or_else(|_| miner.sensible_gas_price())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn signer_disabled_error() -> Error {
|
|
||||||
Error {
|
|
||||||
code: ErrorCode::ServerError(error_codes::SIGNER_DISABLED),
|
|
||||||
message: "Trusted Signer is disabled. This API is not available.".into(),
|
|
||||||
data: None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn signing_error(error: AccountError) -> Error {
|
|
||||||
Error {
|
|
||||||
code: ErrorCode::ServerError(error_codes::ACCOUNT_LOCKED),
|
|
||||||
message: "Your account is locked. Unlock the account via CLI, personal_unlockAccount or use Trusted Signer.".into(),
|
|
||||||
data: Some(Value::String(format!("{:?}", error))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn password_error(error: AccountError) -> Error {
|
|
||||||
Error {
|
|
||||||
code: ErrorCode::ServerError(error_codes::PASSWORD_INVALID),
|
|
||||||
message: "Account password is invalid or account does not exist.".into(),
|
|
||||||
data: Some(Value::String(format!("{:?}", error))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Error returned when request is rejected (in Trusted Signer).
|
|
||||||
pub fn request_rejected_error() -> Error {
|
|
||||||
Error {
|
|
||||||
code: ErrorCode::ServerError(error_codes::REQUEST_REJECTED),
|
|
||||||
message: "Request has been rejected.".into(),
|
|
||||||
data: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Error returned when request is not found in queue.
|
|
||||||
pub fn request_not_found_error() -> Error {
|
|
||||||
Error {
|
|
||||||
code: ErrorCode::ServerError(error_codes::REQUEST_NOT_FOUND),
|
|
||||||
message: "Request not found.".into(),
|
|
||||||
data: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn transaction_error(error: EthcoreError) -> Error {
|
|
||||||
use ethcore::error::TransactionError::*;
|
|
||||||
|
|
||||||
if let EthcoreError::Transaction(e) = error {
|
|
||||||
let msg = match e {
|
|
||||||
AlreadyImported => "Transaction with the same hash was already imported.".into(),
|
|
||||||
Old => "Transaction nonce is too low. Try incrementing the nonce.".into(),
|
|
||||||
TooCheapToReplace => {
|
|
||||||
"Transaction fee is too low. There is another transaction with same nonce in the queue. Try increasing the fee or incrementing the nonce.".into()
|
|
||||||
},
|
|
||||||
LimitReached => {
|
|
||||||
"There are too many transactions in the queue. Your transaction was dropped due to limit. Try increasing the fee.".into()
|
|
||||||
},
|
|
||||||
InsufficientGasPrice { minimal, got } => {
|
|
||||||
format!("Transaction fee is too low. It does not satisfy your node's minimal fee (minimal: {}, got: {}). Try increasing the fee.", minimal, got)
|
|
||||||
},
|
|
||||||
InsufficientBalance { balance, cost } => {
|
|
||||||
format!("Insufficient funds. Account you try to send transaction from does not have enough funds. Required {} and got: {}.", cost, balance)
|
|
||||||
},
|
|
||||||
GasLimitExceeded { limit, got } => {
|
|
||||||
format!("Transaction cost exceeds current gas limit. Limit: {}, got: {}. Try decreasing supplied gas.", limit, got)
|
|
||||||
},
|
|
||||||
InvalidGasLimit(_) => "Supplied gas is beyond limit.".into(),
|
|
||||||
};
|
|
||||||
Error {
|
|
||||||
code: ErrorCode::ServerError(error_codes::TRANSACTION_ERROR),
|
|
||||||
message: msg,
|
|
||||||
data: None,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Error {
|
|
||||||
code: ErrorCode::ServerError(error_codes::UNKNOWN_ERROR),
|
|
||||||
message: "Unknown error when sending transaction.".into(),
|
|
||||||
data: Some(Value::String(format!("{:?}", error))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -19,6 +19,7 @@ use std::sync::{Arc, Weak};
|
|||||||
use jsonrpc_core::*;
|
use jsonrpc_core::*;
|
||||||
use ethsync::SyncProvider;
|
use ethsync::SyncProvider;
|
||||||
use v1::traits::Net;
|
use v1::traits::Net;
|
||||||
|
use v1::helpers::params::expect_no_params;
|
||||||
|
|
||||||
/// Net rpc implementation.
|
/// Net rpc implementation.
|
||||||
pub struct NetClient<S: ?Sized> where S: SyncProvider {
|
pub struct NetClient<S: ?Sized> where S: SyncProvider {
|
||||||
@ -35,15 +36,18 @@ impl<S: ?Sized> NetClient<S> where S: SyncProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<S: ?Sized> Net for NetClient<S> where S: SyncProvider + 'static {
|
impl<S: ?Sized> Net for NetClient<S> where S: SyncProvider + 'static {
|
||||||
fn version(&self, _: Params) -> Result<Value, Error> {
|
fn version(&self, params: Params) -> Result<Value, Error> {
|
||||||
|
try!(expect_no_params(params));
|
||||||
Ok(Value::String(format!("{}", take_weak!(self.sync).status().network_id).to_owned()))
|
Ok(Value::String(format!("{}", take_weak!(self.sync).status().network_id).to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peer_count(&self, _params: Params) -> Result<Value, Error> {
|
fn peer_count(&self, params: Params) -> Result<Value, Error> {
|
||||||
|
try!(expect_no_params(params));
|
||||||
Ok(Value::String(format!("0x{:x}", take_weak!(self.sync).status().num_peers as u64).to_owned()))
|
Ok(Value::String(format!("0x{:x}", take_weak!(self.sync).status().num_peers as u64).to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_listening(&self, _: Params) -> Result<Value, Error> {
|
fn is_listening(&self, params: Params) -> Result<Value, Error> {
|
||||||
|
try!(expect_no_params(params));
|
||||||
// right now (11 march 2016), we are always listening for incoming connections
|
// right now (11 march 2016), we are always listening for incoming connections
|
||||||
Ok(Value::Bool(true))
|
Ok(Value::Bool(true))
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,9 @@ use std::collections::{BTreeMap};
|
|||||||
use jsonrpc_core::*;
|
use jsonrpc_core::*;
|
||||||
use v1::traits::Personal;
|
use v1::traits::Personal;
|
||||||
use v1::types::{H160 as RpcH160, TransactionRequest};
|
use v1::types::{H160 as RpcH160, TransactionRequest};
|
||||||
use v1::impls::unlock_sign_and_dispatch;
|
use v1::helpers::{errors, TransactionRequest as TRequest};
|
||||||
use v1::helpers::{TransactionRequest as TRequest};
|
use v1::helpers::params::expect_no_params;
|
||||||
|
use v1::helpers::dispatch::unlock_sign_and_dispatch;
|
||||||
use ethcore::account_provider::AccountProvider;
|
use ethcore::account_provider::AccountProvider;
|
||||||
use util::Address;
|
use util::Address;
|
||||||
use ethcore::client::MiningBlockChainClient;
|
use ethcore::client::MiningBlockChainClient;
|
||||||
@ -57,8 +58,10 @@ impl<C, M> PersonalClient<C, M> where C: MiningBlockChainClient, M: MinerService
|
|||||||
|
|
||||||
impl<C: 'static, M: 'static> Personal for PersonalClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
impl<C: 'static, M: 'static> Personal for PersonalClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
||||||
|
|
||||||
fn signer_enabled(&self, _: Params) -> Result<Value, Error> {
|
fn signer_enabled(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
|
try!(expect_no_params(params));
|
||||||
|
|
||||||
self.signer_port
|
self.signer_port
|
||||||
.map(|v| to_value(&v))
|
.map(|v| to_value(&v))
|
||||||
.unwrap_or_else(|| to_value(&false))
|
.unwrap_or_else(|| to_value(&false))
|
||||||
@ -66,14 +69,11 @@ impl<C: 'static, M: 'static> Personal for PersonalClient<C, M> where C: MiningBl
|
|||||||
|
|
||||||
fn accounts(&self, params: Params) -> Result<Value, Error> {
|
fn accounts(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
match params {
|
try!(expect_no_params(params));
|
||||||
Params::None => {
|
|
||||||
let store = take_weak!(self.accounts);
|
let store = take_weak!(self.accounts);
|
||||||
let accounts = try!(store.accounts().map_err(|_| Error::internal_error()));
|
let accounts = try!(store.accounts().map_err(|e| errors::internal("Could not fetch accounts.", e)));
|
||||||
to_value(&accounts.into_iter().map(Into::into).collect::<Vec<RpcH160>>())
|
to_value(&accounts.into_iter().map(Into::into).collect::<Vec<RpcH160>>())
|
||||||
},
|
|
||||||
_ => Err(Error::invalid_params())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_account(&self, params: Params) -> Result<Value, Error> {
|
fn new_account(&self, params: Params) -> Result<Value, Error> {
|
||||||
@ -83,7 +83,7 @@ impl<C: 'static, M: 'static> Personal for PersonalClient<C, M> where C: MiningBl
|
|||||||
let store = take_weak!(self.accounts);
|
let store = take_weak!(self.accounts);
|
||||||
match store.new_account(&pass) {
|
match store.new_account(&pass) {
|
||||||
Ok(address) => to_value(&RpcH160::from(address)),
|
Ok(address) => to_value(&RpcH160::from(address)),
|
||||||
Err(_) => Err(Error::internal_error())
|
Err(e) => Err(errors::account("Could not create account.", e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -124,7 +124,7 @@ impl<C: 'static, M: 'static> Personal for PersonalClient<C, M> where C: MiningBl
|
|||||||
let store = take_weak!(self.accounts);
|
let store = take_weak!(self.accounts);
|
||||||
from_params::<(RpcH160, _)>(params).and_then(|(addr, name)| {
|
from_params::<(RpcH160, _)>(params).and_then(|(addr, name)| {
|
||||||
let addr: Address = addr.into();
|
let addr: Address = addr.into();
|
||||||
store.set_account_name(addr, name).map_err(|_| Error::invalid_params()).map(|_| Value::Null)
|
store.set_account_name(addr, name).map_err(|e| errors::account("Could not set account name.", e)).map(|_| Value::Null)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,14 +133,16 @@ impl<C: 'static, M: 'static> Personal for PersonalClient<C, M> where C: MiningBl
|
|||||||
let store = take_weak!(self.accounts);
|
let store = take_weak!(self.accounts);
|
||||||
from_params::<(RpcH160, _)>(params).and_then(|(addr, meta)| {
|
from_params::<(RpcH160, _)>(params).and_then(|(addr, meta)| {
|
||||||
let addr: Address = addr.into();
|
let addr: Address = addr.into();
|
||||||
store.set_account_meta(addr, meta).map_err(|_| Error::invalid_params()).map(|_| Value::Null)
|
store.set_account_meta(addr, meta).map_err(|e| errors::account("Could not set account meta.", e)).map(|_| Value::Null)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn accounts_info(&self, _: Params) -> Result<Value, Error> {
|
fn accounts_info(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
|
try!(expect_no_params(params));
|
||||||
let store = take_weak!(self.accounts);
|
let store = take_weak!(self.accounts);
|
||||||
Ok(Value::Object(try!(store.accounts_info().map_err(|_| Error::invalid_params())).into_iter().map(|(a, v)| {
|
let info = try!(store.accounts_info().map_err(|e| errors::account("Could not fetch account info.", e)));
|
||||||
|
Ok(Value::Object(info.into_iter().map(|(a, v)| {
|
||||||
let m = map![
|
let m = map![
|
||||||
"name".to_owned() => to_value(&v.name).unwrap(),
|
"name".to_owned() => to_value(&v.name).unwrap(),
|
||||||
"meta".to_owned() => to_value(&v.meta).unwrap(),
|
"meta".to_owned() => to_value(&v.meta).unwrap(),
|
||||||
|
@ -23,8 +23,9 @@ use ethcore::client::MiningBlockChainClient;
|
|||||||
use ethcore::miner::MinerService;
|
use ethcore::miner::MinerService;
|
||||||
use v1::traits::PersonalSigner;
|
use v1::traits::PersonalSigner;
|
||||||
use v1::types::{TransactionModification, ConfirmationRequest, U256};
|
use v1::types::{TransactionModification, ConfirmationRequest, U256};
|
||||||
use v1::impls::{unlock_sign_and_dispatch, signature_with_password};
|
use v1::helpers::{errors, SigningQueue, ConfirmationsQueue, ConfirmationPayload};
|
||||||
use v1::helpers::{SigningQueue, ConfirmationsQueue, ConfirmationPayload};
|
use v1::helpers::params::expect_no_params;
|
||||||
|
use v1::helpers::dispatch::{unlock_sign_and_dispatch, signature_with_password};
|
||||||
|
|
||||||
/// Transactions confirmation (personal) rpc implementation.
|
/// Transactions confirmation (personal) rpc implementation.
|
||||||
pub struct SignerClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
pub struct SignerClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
||||||
@ -55,8 +56,9 @@ impl<C: 'static, M: 'static> SignerClient<C, M> where C: MiningBlockChainClient,
|
|||||||
|
|
||||||
impl<C: 'static, M: 'static> PersonalSigner for SignerClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
impl<C: 'static, M: 'static> PersonalSigner for SignerClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
||||||
|
|
||||||
fn requests_to_confirm(&self, _params: Params) -> Result<Value, Error> {
|
fn requests_to_confirm(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
|
try!(expect_no_params(params));
|
||||||
let queue = take_weak!(self.queue);
|
let queue = take_weak!(self.queue);
|
||||||
to_value(&queue.requests().into_iter().map(From::from).collect::<Vec<ConfirmationRequest>>())
|
to_value(&queue.requests().into_iter().map(From::from).collect::<Vec<ConfirmationRequest>>())
|
||||||
}
|
}
|
||||||
@ -91,7 +93,7 @@ impl<C: 'static, M: 'static> PersonalSigner for SignerClient<C, M> where C: Mini
|
|||||||
queue.request_confirmed(id, Ok(response.clone()));
|
queue.request_confirmed(id, Ok(response.clone()));
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}).unwrap_or_else(|| Err(Error::invalid_params()))
|
}).unwrap_or_else(|| Err(errors::invalid_params("Unknown RequestID", id)))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use jsonrpc_core::*;
|
use jsonrpc_core::*;
|
||||||
use v1::traits::Rpc;
|
use v1::traits::Rpc;
|
||||||
|
use v1::helpers::params::expect_no_params;
|
||||||
|
|
||||||
/// RPC generic methods implementation.
|
/// RPC generic methods implementation.
|
||||||
pub struct RpcClient {
|
pub struct RpcClient {
|
||||||
@ -39,7 +40,8 @@ impl RpcClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Rpc for RpcClient {
|
impl Rpc for RpcClient {
|
||||||
fn rpc_modules(&self, _: Params) -> Result<Value, Error> {
|
fn rpc_modules(&self, params: Params) -> Result<Value, Error> {
|
||||||
|
try!(expect_no_params(params));
|
||||||
let modules = self.modules.iter()
|
let modules = self.modules.iter()
|
||||||
.fold(BTreeMap::new(), |mut map, (k, v)| {
|
.fold(BTreeMap::new(), |mut map, (k, v)| {
|
||||||
map.insert(k.to_owned(), Value::String(v.to_owned()));
|
map.insert(k.to_owned(), Value::String(v.to_owned()));
|
||||||
@ -48,7 +50,8 @@ impl Rpc for RpcClient {
|
|||||||
Ok(Value::Object(modules))
|
Ok(Value::Object(modules))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn modules(&self, _: Params) -> Result<Value, Error> {
|
fn modules(&self, params: Params) -> Result<Value, Error> {
|
||||||
|
try!(expect_no_params(params));
|
||||||
let modules = self.modules.iter()
|
let modules = self.modules.iter()
|
||||||
.filter(|&(k, _v)| {
|
.filter(|&(k, _v)| {
|
||||||
self.valid_apis.contains(k)
|
self.valid_apis.contains(k)
|
||||||
|
@ -23,9 +23,9 @@ use ethcore::client::{BlockChainClient, CallAnalytics, TransactionID, TraceId};
|
|||||||
use ethcore::miner::MinerService;
|
use ethcore::miner::MinerService;
|
||||||
use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Action};
|
use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Action};
|
||||||
use v1::traits::Traces;
|
use v1::traits::Traces;
|
||||||
use v1::helpers::CallRequest as CRequest;
|
use v1::helpers::{errors, CallRequest as CRequest};
|
||||||
|
use v1::helpers::params::from_params_default_third;
|
||||||
use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, H256};
|
use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, H256};
|
||||||
use v1::impls::from_params_default_third;
|
|
||||||
|
|
||||||
fn to_call_analytics(flags: Vec<String>) -> CallAnalytics {
|
fn to_call_analytics(flags: Vec<String>) -> CallAnalytics {
|
||||||
CallAnalytics {
|
CallAnalytics {
|
||||||
@ -144,7 +144,7 @@ impl<C, M> Traces for TracesClient<C, M> where C: BlockChainClient + 'static, M:
|
|||||||
Ok(e) => to_value(&TraceResults::from(e)),
|
Ok(e) => to_value(&TraceResults::from(e)),
|
||||||
_ => Ok(Value::Null),
|
_ => Ok(Value::Null),
|
||||||
},
|
},
|
||||||
Err(_) => Err(Error::invalid_params()),
|
Err(e) => Err(errors::invalid_params("Transaction is not valid RLP", e)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ use jsonrpc_core::*;
|
|||||||
use util::version;
|
use util::version;
|
||||||
use v1::traits::Web3;
|
use v1::traits::Web3;
|
||||||
use v1::types::{H256, Bytes};
|
use v1::types::{H256, Bytes};
|
||||||
|
use v1::helpers::params::expect_no_params;
|
||||||
use util::sha3::Hashable;
|
use util::sha3::Hashable;
|
||||||
|
|
||||||
/// Web3 rpc implementation.
|
/// Web3 rpc implementation.
|
||||||
@ -31,10 +32,8 @@ impl Web3Client {
|
|||||||
|
|
||||||
impl Web3 for Web3Client {
|
impl Web3 for Web3Client {
|
||||||
fn client_version(&self, params: Params) -> Result<Value, Error> {
|
fn client_version(&self, params: Params) -> Result<Value, Error> {
|
||||||
match params {
|
try!(expect_no_params(params));
|
||||||
Params::None => Ok(Value::String(version().to_owned().replace("Parity/", "Parity//"))),
|
Ok(Value::String(version().to_owned().replace("Parity/", "Parity//")))
|
||||||
_ => Err(Error::invalid_params())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sha3(&self, params: Params) -> Result<Value, Error> {
|
fn sha3(&self, params: Params) -> Result<Value, Error> {
|
||||||
|
@ -18,8 +18,9 @@
|
|||||||
//!
|
//!
|
||||||
//! Compliant with ethereum rpc.
|
//! Compliant with ethereum rpc.
|
||||||
|
|
||||||
mod impls;
|
#[macro_use]
|
||||||
mod helpers;
|
mod helpers;
|
||||||
|
mod impls;
|
||||||
|
|
||||||
pub mod traits;
|
pub mod traits;
|
||||||
pub mod tests;
|
pub mod tests;
|
||||||
|
@ -12,10 +12,10 @@ rustc_version = "0.1"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rand = "0.3.14"
|
rand = "0.3.14"
|
||||||
jsonrpc-core = "2.0"
|
jsonrpc-core = "2.1"
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
env_logger = "0.3"
|
env_logger = "0.3"
|
||||||
ws = { git = "https://github.com/ethcore/ws-rs.git", branch = "stable" }
|
ws = { git = "https://github.com/ethcore/ws-rs.git", branch = "mio-upstream-stable" }
|
||||||
ethcore-util = { path = "../util" }
|
ethcore-util = { path = "../util" }
|
||||||
ethcore-io = { path = "../util/io" }
|
ethcore-io = { path = "../util/io" }
|
||||||
ethcore-rpc = { path = "../rpc" }
|
ethcore-rpc = { path = "../rpc" }
|
||||||
|
@ -46,7 +46,7 @@ impl TimeProvider for DefaultTimeProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// No of seconds the hash is valid
|
/// No of seconds the hash is valid
|
||||||
const TIME_THRESHOLD: u64 = 2;
|
const TIME_THRESHOLD: u64 = 7;
|
||||||
const TOKEN_LENGTH: usize = 16;
|
const TOKEN_LENGTH: usize = 16;
|
||||||
|
|
||||||
/// Manages authorization codes for `SignerUIs`
|
/// Manages authorization codes for `SignerUIs`
|
||||||
@ -102,7 +102,7 @@ impl<T: TimeProvider> AuthCodes<T> {
|
|||||||
let now = self.now.now();
|
let now = self.now.now();
|
||||||
// check time
|
// check time
|
||||||
if time >= now + TIME_THRESHOLD || time <= now - TIME_THRESHOLD {
|
if time >= now + TIME_THRESHOLD || time <= now - TIME_THRESHOLD {
|
||||||
warn!(target: "signer", "Received old authentication request.");
|
warn!(target: "signer", "Received old authentication request. ({} vs {})", now, time);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,8 +169,8 @@ mod tests {
|
|||||||
fn should_return_false_if_hash_is_valid_but_time_is_invalid() {
|
fn should_return_false_if_hash_is_valid_but_time_is_invalid() {
|
||||||
// given
|
// given
|
||||||
let code = "23521352asdfasdfadf";
|
let code = "23521352asdfasdfadf";
|
||||||
let time = 105;
|
let time = 107;
|
||||||
let time2 = 95;
|
let time2 = 93;
|
||||||
let codes = AuthCodes::new(vec![code.into()], || 100);
|
let codes = AuthCodes::new(vec![code.into()], || 100);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
|
@ -146,7 +146,9 @@ impl ws::Handler for Session {
|
|||||||
fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
|
fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
|
||||||
let req = try!(msg.as_text());
|
let req = try!(msg.as_text());
|
||||||
match self.handler.handle_request(req) {
|
match self.handler.handle_request(req) {
|
||||||
Some(res) => self.out.send(res),
|
Some(res) => {
|
||||||
|
self.out.send(res)
|
||||||
|
},
|
||||||
None => Ok(()),
|
None => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1376,27 +1376,23 @@ impl ChainSync {
|
|||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_lagging_peers(&mut self, chain_info: &BlockChainInfo, io: &mut SyncIo) -> Vec<(PeerId, BlockNumber)> {
|
fn select_random_lagging_peers(&mut self, peers: &[(PeerId, BlockNumber)]) -> Vec<(PeerId, BlockNumber)> {
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
let mut lagging_peers = self.get_lagging_peers(chain_info, io);
|
|
||||||
// take sqrt(x) peers
|
// take sqrt(x) peers
|
||||||
|
let mut peers = peers.to_vec();
|
||||||
let mut count = (self.peers.len() as f64).powf(0.5).round() as usize;
|
let mut count = (self.peers.len() as f64).powf(0.5).round() as usize;
|
||||||
count = min(count, MAX_PEERS_PROPAGATION);
|
count = min(count, MAX_PEERS_PROPAGATION);
|
||||||
count = max(count, MIN_PEERS_PROPAGATION);
|
count = max(count, MIN_PEERS_PROPAGATION);
|
||||||
::rand::thread_rng().shuffle(&mut lagging_peers);
|
::rand::thread_rng().shuffle(&mut peers);
|
||||||
lagging_peers.into_iter().take(count).collect::<Vec<_>>()
|
peers.truncate(count);
|
||||||
|
peers
|
||||||
}
|
}
|
||||||
|
|
||||||
/// propagates latest block to lagging peers
|
/// propagates latest block to lagging peers
|
||||||
fn propagate_blocks(&mut self, chain_info: &BlockChainInfo, io: &mut SyncIo, sealed: &[H256]) -> usize {
|
fn propagate_blocks(&mut self, chain_info: &BlockChainInfo, io: &mut SyncIo, sealed: &[H256], peers: &[(PeerId, BlockNumber)]) -> usize {
|
||||||
let lucky_peers: Vec<_> = if sealed.is_empty() {
|
trace!(target: "sync", "Sending NewBlocks to {:?}", peers);
|
||||||
self.select_lagging_peers(chain_info, io).iter().map(|&(id, _)| id).collect()
|
|
||||||
} else {
|
|
||||||
self.peers.keys().cloned().collect()
|
|
||||||
};
|
|
||||||
trace!(target: "sync", "Sending NewBlocks to {:?}", lucky_peers);
|
|
||||||
let mut sent = 0;
|
let mut sent = 0;
|
||||||
for peer_id in lucky_peers {
|
for &(peer_id, _) in peers {
|
||||||
if sealed.is_empty() {
|
if sealed.is_empty() {
|
||||||
let rlp = ChainSync::create_latest_block_rlp(io.chain());
|
let rlp = ChainSync::create_latest_block_rlp(io.chain());
|
||||||
self.send_packet(io, peer_id, NEW_BLOCK_PACKET, rlp);
|
self.send_packet(io, peer_id, NEW_BLOCK_PACKET, rlp);
|
||||||
@ -1414,12 +1410,11 @@ impl ChainSync {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// propagates new known hashes to all peers
|
/// propagates new known hashes to all peers
|
||||||
fn propagate_new_hashes(&mut self, chain_info: &BlockChainInfo, io: &mut SyncIo) -> usize {
|
fn propagate_new_hashes(&mut self, chain_info: &BlockChainInfo, io: &mut SyncIo, peers: &[(PeerId, BlockNumber)]) -> usize {
|
||||||
let lucky_peers = self.select_lagging_peers(chain_info, io);
|
trace!(target: "sync", "Sending NewHashes to {:?}", peers);
|
||||||
trace!(target: "sync", "Sending NewHashes to {:?}", lucky_peers);
|
|
||||||
let mut sent = 0;
|
let mut sent = 0;
|
||||||
let last_parent = HeaderView::new(&io.chain().block_header(BlockID::Hash(chain_info.best_block_hash.clone())).unwrap()).parent_hash();
|
let last_parent = HeaderView::new(&io.chain().block_header(BlockID::Hash(chain_info.best_block_hash.clone())).unwrap()).parent_hash();
|
||||||
for (peer_id, peer_number) in lucky_peers {
|
for &(peer_id, peer_number) in peers {
|
||||||
let peer_best = if chain_info.best_block_number - peer_number > MAX_PEER_LAG_PROPAGATION as BlockNumber {
|
let peer_best = if chain_info.best_block_number - peer_number > MAX_PEER_LAG_PROPAGATION as BlockNumber {
|
||||||
// If we think peer is too far behind just send one latest hash
|
// If we think peer is too far behind just send one latest hash
|
||||||
last_parent.clone()
|
last_parent.clone()
|
||||||
@ -1485,11 +1480,19 @@ impl ChainSync {
|
|||||||
fn propagate_latest_blocks(&mut self, io: &mut SyncIo, sealed: &[H256]) {
|
fn propagate_latest_blocks(&mut self, io: &mut SyncIo, sealed: &[H256]) {
|
||||||
let chain_info = io.chain().chain_info();
|
let chain_info = io.chain().chain_info();
|
||||||
if (((chain_info.best_block_number as i64) - (self.last_sent_block_number as i64)).abs() as BlockNumber) < MAX_PEER_LAG_PROPAGATION {
|
if (((chain_info.best_block_number as i64) - (self.last_sent_block_number as i64)).abs() as BlockNumber) < MAX_PEER_LAG_PROPAGATION {
|
||||||
let hashes = self.propagate_new_hashes(&chain_info, io);
|
let mut peers = self.get_lagging_peers(&chain_info, io);
|
||||||
let blocks = self.propagate_blocks(&chain_info, io, sealed);
|
if sealed.is_empty() {
|
||||||
|
let hashes = self.propagate_new_hashes(&chain_info, io, &peers);
|
||||||
|
peers = self.select_random_lagging_peers(&peers);
|
||||||
|
let blocks = self.propagate_blocks(&chain_info, io, sealed, &peers);
|
||||||
if blocks != 0 || hashes != 0 {
|
if blocks != 0 || hashes != 0 {
|
||||||
trace!(target: "sync", "Sent latest {} blocks and {} hashes to peers.", blocks, hashes);
|
trace!(target: "sync", "Sent latest {} blocks and {} hashes to peers.", blocks, hashes);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
self.propagate_blocks(&chain_info, io, sealed, &peers);
|
||||||
|
self.propagate_new_hashes(&chain_info, io, &peers);
|
||||||
|
trace!(target: "sync", "Sent sealed block to all peers");
|
||||||
|
};
|
||||||
}
|
}
|
||||||
self.propagate_new_transactions(io);
|
self.propagate_new_transactions(io);
|
||||||
self.last_sent_block_number = chain_info.best_block_number;
|
self.last_sent_block_number = chain_info.best_block_number;
|
||||||
@ -1757,7 +1760,8 @@ mod tests {
|
|||||||
let chain_info = client.chain_info();
|
let chain_info = client.chain_info();
|
||||||
let mut io = TestIo::new(&mut client, &mut queue, None);
|
let mut io = TestIo::new(&mut client, &mut queue, None);
|
||||||
|
|
||||||
let peer_count = sync.propagate_new_hashes(&chain_info, &mut io);
|
let peers = sync.get_lagging_peers(&chain_info, &mut io);
|
||||||
|
let peer_count = sync.propagate_new_hashes(&chain_info, &mut io, &peers);
|
||||||
|
|
||||||
// 1 message should be send
|
// 1 message should be send
|
||||||
assert_eq!(1, io.queue.len());
|
assert_eq!(1, io.queue.len());
|
||||||
@ -1775,7 +1779,8 @@ mod tests {
|
|||||||
let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client);
|
let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client);
|
||||||
let chain_info = client.chain_info();
|
let chain_info = client.chain_info();
|
||||||
let mut io = TestIo::new(&mut client, &mut queue, None);
|
let mut io = TestIo::new(&mut client, &mut queue, None);
|
||||||
let peer_count = sync.propagate_blocks(&chain_info, &mut io, &[]);
|
let peers = sync.get_lagging_peers(&chain_info, &mut io);
|
||||||
|
let peer_count = sync.propagate_blocks(&chain_info, &mut io, &[], &peers);
|
||||||
|
|
||||||
// 1 message should be send
|
// 1 message should be send
|
||||||
assert_eq!(1, io.queue.len());
|
assert_eq!(1, io.queue.len());
|
||||||
@ -1794,7 +1799,8 @@ mod tests {
|
|||||||
let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client);
|
let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client);
|
||||||
let chain_info = client.chain_info();
|
let chain_info = client.chain_info();
|
||||||
let mut io = TestIo::new(&mut client, &mut queue, None);
|
let mut io = TestIo::new(&mut client, &mut queue, None);
|
||||||
let peer_count = sync.propagate_blocks(&chain_info, &mut io, &[hash.clone()]);
|
let peers = sync.get_lagging_peers(&chain_info, &mut io);
|
||||||
|
let peer_count = sync.propagate_blocks(&chain_info, &mut io, &[hash.clone()], &peers);
|
||||||
|
|
||||||
// 1 message should be send
|
// 1 message should be send
|
||||||
assert_eq!(1, io.queue.len());
|
assert_eq!(1, io.queue.len());
|
||||||
@ -1900,7 +1906,8 @@ mod tests {
|
|||||||
let chain_info = client.chain_info();
|
let chain_info = client.chain_info();
|
||||||
let mut io = TestIo::new(&mut client, &mut queue, None);
|
let mut io = TestIo::new(&mut client, &mut queue, None);
|
||||||
|
|
||||||
sync.propagate_new_hashes(&chain_info, &mut io);
|
let peers = sync.get_lagging_peers(&chain_info, &mut io);
|
||||||
|
sync.propagate_new_hashes(&chain_info, &mut io, &peers);
|
||||||
|
|
||||||
let data = &io.queue[0].data.clone();
|
let data = &io.queue[0].data.clone();
|
||||||
let result = sync.on_peer_new_hashes(&mut io, 0, &UntrustedRlp::new(data));
|
let result = sync.on_peer_new_hashes(&mut io, 0, &UntrustedRlp::new(data));
|
||||||
@ -1918,7 +1925,8 @@ mod tests {
|
|||||||
let chain_info = client.chain_info();
|
let chain_info = client.chain_info();
|
||||||
let mut io = TestIo::new(&mut client, &mut queue, None);
|
let mut io = TestIo::new(&mut client, &mut queue, None);
|
||||||
|
|
||||||
sync.propagate_blocks(&chain_info, &mut io, &[]);
|
let peers = sync.get_lagging_peers(&chain_info, &mut io);
|
||||||
|
sync.propagate_blocks(&chain_info, &mut io, &[], &peers);
|
||||||
|
|
||||||
let data = &io.queue[0].data.clone();
|
let data = &io.queue[0].data.clone();
|
||||||
let result = sync.on_peer_new_block(&mut io, 0, &UntrustedRlp::new(data));
|
let result = sync.on_peer_new_block(&mut io, 0, &UntrustedRlp::new(data));
|
||||||
|
@ -161,11 +161,11 @@ fn propagate_hashes() {
|
|||||||
net.trigger_chain_new_blocks(0); //first event just sets the marker
|
net.trigger_chain_new_blocks(0); //first event just sets the marker
|
||||||
net.trigger_chain_new_blocks(0);
|
net.trigger_chain_new_blocks(0);
|
||||||
|
|
||||||
// 5 peers to sync
|
// 5 peers with NewHahses, 4 with blocks
|
||||||
assert_eq!(5, net.peer(0).queue.len());
|
assert_eq!(9, net.peer(0).queue.len());
|
||||||
let mut hashes = 0;
|
let mut hashes = 0;
|
||||||
let mut blocks = 0;
|
let mut blocks = 0;
|
||||||
for i in 0..5 {
|
for i in 0..net.peer(0).queue.len() {
|
||||||
if net.peer(0).queue[i].packet_id == 0x1 {
|
if net.peer(0).queue[i].packet_id == 0x1 {
|
||||||
hashes += 1;
|
hashes += 1;
|
||||||
}
|
}
|
||||||
@ -173,7 +173,8 @@ fn propagate_hashes() {
|
|||||||
blocks += 1;
|
blocks += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert!(blocks + hashes == 5);
|
assert_eq!(blocks, 4);
|
||||||
|
assert_eq!(hashes, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -172,7 +172,7 @@ impl Default for DatabaseConfig {
|
|||||||
fn default() -> DatabaseConfig {
|
fn default() -> DatabaseConfig {
|
||||||
DatabaseConfig {
|
DatabaseConfig {
|
||||||
cache_size: None,
|
cache_size: None,
|
||||||
max_open_files: 1024,
|
max_open_files: 512,
|
||||||
compaction: CompactionProfile::default(),
|
compaction: CompactionProfile::default(),
|
||||||
columns: None,
|
columns: None,
|
||||||
wal: true,
|
wal: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user