mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 17:41:08 +00:00
Merge branch 'master' into gav-storage-root-verify
This commit is contained in:
Generated
+465
-50
@@ -46,7 +46,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.3"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -98,6 +98,11 @@ name = "bitflags"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "blake2-rfc"
|
||||
version = "0.2.18"
|
||||
@@ -160,6 +165,11 @@ name = "constant_time_eq"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.1.6"
|
||||
@@ -184,6 +194,11 @@ name = "dtoa"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "edit-distance"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.4.0"
|
||||
@@ -215,7 +230,31 @@ name = "error-chain"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "eth-secp256k1"
|
||||
version = "0.5.6"
|
||||
source = "git+https://github.com/paritytech/rust-secp256k1#b6b67055edc929057e97d64f036c78ad91f58a7f"
|
||||
dependencies = [
|
||||
"arrayvec 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethcore-bigint"
|
||||
version = "0.2.1"
|
||||
source = "git+https://github.com/paritytech/parity.git#dde6baedeca4b2dccaf2eacfbd2453b3d191596e"
|
||||
dependencies = [
|
||||
"bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plain_hasher 0.1.0 (git+https://github.com/paritytech/parity.git)",
|
||||
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -231,11 +270,44 @@ dependencies = [
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethcore-bytes"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/paritytech/parity.git#dde6baedeca4b2dccaf2eacfbd2453b3d191596e"
|
||||
|
||||
[[package]]
|
||||
name = "ethcore-bytes"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "ethcore-io"
|
||||
version = "1.9.0"
|
||||
source = "git+https://github.com/paritytech/parity.git#dde6baedeca4b2dccaf2eacfbd2453b3d191596e"
|
||||
dependencies = [
|
||||
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethcore-logger"
|
||||
version = "1.9.0"
|
||||
source = "git+https://github.com/paritytech/parity.git#dde6baedeca4b2dccaf2eacfbd2453b3d191596e"
|
||||
dependencies = [
|
||||
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"isatty 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethcore-logger"
|
||||
version = "1.9.0"
|
||||
@@ -245,13 +317,77 @@ dependencies = [
|
||||
"arrayvec 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"isatty 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethcore-network"
|
||||
version = "1.9.0"
|
||||
source = "git+https://github.com/paritytech/parity.git#dde6baedeca4b2dccaf2eacfbd2453b3d191596e"
|
||||
dependencies = [
|
||||
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-bigint 0.2.1 (git+https://github.com/paritytech/parity.git)",
|
||||
"ethcore-bytes 0.1.0 (git+https://github.com/paritytech/parity.git)",
|
||||
"ethcore-io 1.9.0 (git+https://github.com/paritytech/parity.git)",
|
||||
"ethcore-logger 1.9.0 (git+https://github.com/paritytech/parity.git)",
|
||||
"ethcrypto 0.1.0 (git+https://github.com/paritytech/parity.git)",
|
||||
"ethkey 0.3.0 (git+https://github.com/paritytech/parity.git)",
|
||||
"igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"keccak-hash 0.1.0 (git+https://github.com/paritytech/parity.git)",
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"path 0.1.0 (git+https://github.com/paritytech/parity.git)",
|
||||
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rlp 0.2.1 (git+https://github.com/paritytech/parity.git)",
|
||||
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)",
|
||||
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethcrypto"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/paritytech/parity.git#dde6baedeca4b2dccaf2eacfbd2453b3d191596e"
|
||||
dependencies = [
|
||||
"eth-secp256k1 0.5.6 (git+https://github.com/paritytech/rust-secp256k1)",
|
||||
"ethcore-bigint 0.2.1 (git+https://github.com/paritytech/parity.git)",
|
||||
"ethkey 0.3.0 (git+https://github.com/paritytech/parity.git)",
|
||||
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"subtle 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethkey"
|
||||
version = "0.3.0"
|
||||
source = "git+https://github.com/paritytech/parity.git#dde6baedeca4b2dccaf2eacfbd2453b3d191596e"
|
||||
dependencies = [
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"edit-distance 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"eth-secp256k1 0.5.6 (git+https://github.com/paritytech/rust-secp256k1)",
|
||||
"ethcore-bigint 0.2.1 (git+https://github.com/paritytech/parity.git)",
|
||||
"lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixed-hash"
|
||||
version = "0.1.0"
|
||||
@@ -301,6 +437,9 @@ dependencies = [
|
||||
name = "gcc"
|
||||
version = "0.3.54"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "globset"
|
||||
@@ -355,7 +494,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.11.6"
|
||||
version = "0.10.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"traitobject 0.1.0 (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.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.11.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -373,7 +530,29 @@ dependencies = [
|
||||
"tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicase 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "igd"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"xml-rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"xmltree 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -385,6 +564,11 @@ dependencies = [
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnetwork"
|
||||
version = "0.12.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "isatty"
|
||||
version = "0.1.5"
|
||||
@@ -395,6 +579,14 @@ dependencies = [
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.3.4"
|
||||
@@ -403,42 +595,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
[[package]]
|
||||
name = "jsonrpc-core"
|
||||
version = "8.0.0"
|
||||
source = "git+https://github.com/paritytech/jsonrpc.git#8f921ed65cda3fba0ce55d31ed62c7f0c3b32966"
|
||||
source = "git+https://github.com/paritytech/jsonrpc.git#0eba7e745b0895b4234cd8d89b28e10e2c3c34a4"
|
||||
dependencies = [
|
||||
"futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jsonrpc-http-server"
|
||||
version = "8.0.0"
|
||||
source = "git+https://github.com/paritytech/jsonrpc.git#8f921ed65cda3fba0ce55d31ed62c7f0c3b32966"
|
||||
source = "git+https://github.com/paritytech/jsonrpc.git#0eba7e745b0895b4234cd8d89b28e10e2c3c34a4"
|
||||
dependencies = [
|
||||
"hyper 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.11.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)",
|
||||
"jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicase 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jsonrpc-macros"
|
||||
version = "8.0.0"
|
||||
source = "git+https://github.com/paritytech/jsonrpc.git#8f921ed65cda3fba0ce55d31ed62c7f0c3b32966"
|
||||
source = "git+https://github.com/paritytech/jsonrpc.git#0eba7e745b0895b4234cd8d89b28e10e2c3c34a4"
|
||||
dependencies = [
|
||||
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)",
|
||||
"jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)",
|
||||
"serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jsonrpc-pubsub"
|
||||
version = "8.0.0"
|
||||
source = "git+https://github.com/paritytech/jsonrpc.git#8f921ed65cda3fba0ce55d31ed62c7f0c3b32966"
|
||||
source = "git+https://github.com/paritytech/jsonrpc.git#0eba7e745b0895b4234cd8d89b28e10e2c3c34a4"
|
||||
dependencies = [
|
||||
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -448,7 +640,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "jsonrpc-server-utils"
|
||||
version = "8.0.0"
|
||||
source = "git+https://github.com/paritytech/jsonrpc.git#8f921ed65cda3fba0ce55d31ed62c7f0c3b32966"
|
||||
source = "git+https://github.com/paritytech/jsonrpc.git#0eba7e745b0895b4234cd8d89b28e10e2c3c34a4"
|
||||
dependencies = [
|
||||
"bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"globset 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -458,6 +650,16 @@ dependencies = [
|
||||
"tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "keccak-hash"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/paritytech/parity.git#dde6baedeca4b2dccaf2eacfbd2453b3d191596e"
|
||||
dependencies = [
|
||||
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-bigint 0.2.1 (git+https://github.com/paritytech/parity.git)",
|
||||
"tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "keccak-hash"
|
||||
version = "0.1.0"
|
||||
@@ -484,7 +686,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "0.2.9"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -507,6 +709,11 @@ name = "log"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "matches"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "1.0.2"
|
||||
@@ -529,12 +736,20 @@ dependencies = [
|
||||
"rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicase 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -628,6 +843,16 @@ dependencies = [
|
||||
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parity-wordlist"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.4.8"
|
||||
@@ -658,6 +883,11 @@ dependencies = [
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "path"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/paritytech/parity.git#dde6baedeca4b2dccaf2eacfbd2453b3d191596e"
|
||||
|
||||
[[package]]
|
||||
name = "patricia-trie"
|
||||
version = "0.1.0"
|
||||
@@ -681,6 +911,14 @@ name = "percent-encoding"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "plain_hasher"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/paritytech/parity.git#dde6baedeca4b2dccaf2eacfbd2453b3d191596e"
|
||||
dependencies = [
|
||||
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plain_hasher"
|
||||
version = "0.1.0"
|
||||
@@ -695,6 +933,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"polkadot-cli 0.1.0",
|
||||
"polkadot-network 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -725,7 +964,10 @@ name = "polkadot-client"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"polkadot-primitives 0.1.0",
|
||||
"polkadot-serializer 0.1.0",
|
||||
"polkadot-state-machine 0.1.0",
|
||||
]
|
||||
|
||||
@@ -752,8 +994,33 @@ dependencies = [
|
||||
"polkadot-state-machine 0.1.0",
|
||||
"runtime-std 0.1.0",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polkadot-network"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-io 1.9.0 (git+https://github.com/paritytech/parity.git)",
|
||||
"ethcore-network 1.9.0 (git+https://github.com/paritytech/parity.git)",
|
||||
"heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"polkadot-client 0.1.0",
|
||||
"polkadot-primitives 0.1.0",
|
||||
"polkadot-serializer 0.1.0",
|
||||
"polkadot-state-machine 0.1.0",
|
||||
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -768,8 +1035,8 @@ dependencies = [
|
||||
"pretty_assertions 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uint 0.1.0 (git+https://github.com/paritytech/primitives.git)",
|
||||
"untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -802,7 +1069,7 @@ dependencies = [
|
||||
name = "polkadot-serializer"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -826,7 +1093,7 @@ dependencies = [
|
||||
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"polkadot-primitives 0.1.0",
|
||||
"polkadot-serializer 0.1.0",
|
||||
"serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -879,7 +1146,7 @@ version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -929,12 +1196,24 @@ version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rlp"
|
||||
version = "0.2.1"
|
||||
source = "git+https://github.com/paritytech/parity.git#dde6baedeca4b2dccaf2eacfbd2453b3d191596e"
|
||||
dependencies = [
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-bigint 0.2.1 (git+https://github.com/paritytech/parity.git)",
|
||||
"lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rlp"
|
||||
version = "0.2.1"
|
||||
@@ -943,7 +1222,7 @@ dependencies = [
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -958,6 +1237,18 @@ dependencies = [
|
||||
"polkadot-state-machine 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-crypto"
|
||||
version = "0.2.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.5"
|
||||
@@ -969,12 +1260,9 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.1.7"
|
||||
name = "rustc-serialize"
|
||||
version = "0.3.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
@@ -999,11 +1287,6 @@ name = "scopeguard"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.1.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.6.0"
|
||||
@@ -1019,12 +1302,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.19"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.19"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1049,9 +1332,14 @@ dependencies = [
|
||||
"dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.3.0"
|
||||
@@ -1071,6 +1359,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
name = "smallvec"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "snappy"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/paritytech/rust-snappy#858eac97192ea25d18d3f3626a8cc13ca0b175bb"
|
||||
dependencies = [
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"snappy-sys 0.1.0 (git+https://github.com/paritytech/rust-snappy)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "snappy-sys"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/paritytech/rust-snappy#858eac97192ea25d18d3f3626a8cc13ca0b175bb"
|
||||
dependencies = [
|
||||
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
@@ -1082,6 +1391,14 @@ name = "strsim"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.11.11"
|
||||
@@ -1128,7 +1445,7 @@ name = "thread_local"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -1207,6 +1524,11 @@ dependencies = [
|
||||
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "traitobject"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "triehash"
|
||||
version = "0.1.0"
|
||||
@@ -1225,6 +1547,11 @@ dependencies = [
|
||||
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typeable"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "uint"
|
||||
version = "0.1.0"
|
||||
@@ -1237,12 +1564,33 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.0.0"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.4"
|
||||
@@ -1266,6 +1614,16 @@ name = "untrusted"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8-ranges"
|
||||
version = "1.0.0"
|
||||
@@ -1276,6 +1634,11 @@ name = "vec_map"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
@@ -1300,6 +1663,22 @@ dependencies = [
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xml-rs"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xmltree"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"xml-rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
version = "0.3.5"
|
||||
@@ -1312,12 +1691,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
|
||||
"checksum assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e772942dccdf11b368c31e044e4fca9189f80a773d2f0808379de65894cbf57"
|
||||
"checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860"
|
||||
"checksum backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99f2ce94e22b8e664d95c57fff45b98a966c2252b60691d0b7aeeccd88d70983"
|
||||
"checksum backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8709cc7ec06f6f0ae6c2c7e12f6ed41540781f72b488d83734978295ceae182e"
|
||||
"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
|
||||
"checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9"
|
||||
"checksum bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5442186ef6560f30f1ee4b9c1e4c87a35a6879d3644550cc248ec2b955eb5fcd"
|
||||
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
|
||||
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
|
||||
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
|
||||
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
|
||||
"checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d"
|
||||
"checksum bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d828f97b58cc5de3e40c421d0cf2132d6b2da4ee0e11b8632fa838f0f9333ad6"
|
||||
@@ -1326,17 +1706,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b8c532887f1a292d17de05ae858a8fe50a301e196f9ef0ddb7ccd0d1d00f180"
|
||||
"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
|
||||
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
|
||||
"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
|
||||
"checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda"
|
||||
"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
|
||||
"checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8"
|
||||
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
|
||||
"checksum edit-distance 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6a34f5204fbc13582de418611cf3a7dcdd07c6d312a5b631597ba72c06b9d9c9"
|
||||
"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3"
|
||||
"checksum elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "258ff6a9a94f648d0379dbd79110e057edbb53eb85cc237e33eadf8e5a30df85"
|
||||
"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
|
||||
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
|
||||
"checksum eth-secp256k1 0.5.6 (git+https://github.com/paritytech/rust-secp256k1)" = "<none>"
|
||||
"checksum ethcore-bigint 0.2.1 (git+https://github.com/paritytech/parity.git)" = "<none>"
|
||||
"checksum ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb5af77e74a8f70e9c3337e069c37bc82178ef1b459c02091f73c4ad5281eb5"
|
||||
"checksum ethcore-bytes 0.1.0 (git+https://github.com/paritytech/parity.git)" = "<none>"
|
||||
"checksum ethcore-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3977c772cd6c5c22e1c7cfa208e4c3b746bd6c3a6c8eeec0999a6b2103015ad5"
|
||||
"checksum ethcore-io 1.9.0 (git+https://github.com/paritytech/parity.git)" = "<none>"
|
||||
"checksum ethcore-logger 1.9.0 (git+https://github.com/paritytech/parity.git)" = "<none>"
|
||||
"checksum ethcore-logger 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fd5813e49546030be7d134e775088d56b8ff4ab60617b90e93d4f0513da4c5b"
|
||||
"checksum ethcore-network 1.9.0 (git+https://github.com/paritytech/parity.git)" = "<none>"
|
||||
"checksum ethcrypto 0.1.0 (git+https://github.com/paritytech/parity.git)" = "<none>"
|
||||
"checksum ethkey 0.3.0 (git+https://github.com/paritytech/parity.git)" = "<none>"
|
||||
"checksum fixed-hash 0.1.0 (git+https://github.com/paritytech/primitives.git)" = "<none>"
|
||||
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
||||
"checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
|
||||
@@ -1350,25 +1740,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd546ef520ab3745f1aae5f2cdc6de9e6498e94d1ab138b9eb3ddfbf335847fb"
|
||||
"checksum hex-literal-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2ea76da4c7f1a54d01d54985566d3fdd960b2bbd7b970da024821c883c2d9631"
|
||||
"checksum httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "af2f2dd97457e8fb1ae7c5a420db346af389926e36f43768b96f101546b04a07"
|
||||
"checksum hyper 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b45eac8b696d59491b079bd04fcb0f3488c0f6ed62dcb36bcfea8a543e9cdc3"
|
||||
"checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2"
|
||||
"checksum hyper 0.11.7 (registry+https://github.com/rust-lang/crates.io-index)" = "4959ca95f55df4265bff2ad63066147255e6fa733682cf6d1cb5eaff6e53324b"
|
||||
"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
|
||||
"checksum igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "356a0dc23a4fa0f8ce4777258085d00a01ea4923b2efd93538fc44bf5e1bda76"
|
||||
"checksum iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6e8b9c2247fcf6c6a1151f1156932be5606c9fd6f55a2d7f9fc1cb29386b2f7"
|
||||
"checksum ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)" = "2134e210e2a024b5684f90e1556d5f71a1ce7f8b12e9ac9924c67fb36f63b336"
|
||||
"checksum isatty 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "00c9301a947a2eaee7ce2556b80285dcc89558d07088962e6e8b9c25730f9dc6"
|
||||
"checksum itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4833d6978da405305126af4ac88569b5d71ff758581ce5a987dbfa3755f694fc"
|
||||
"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
|
||||
"checksum jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "<none>"
|
||||
"checksum jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "<none>"
|
||||
"checksum jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "<none>"
|
||||
"checksum jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "<none>"
|
||||
"checksum jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "<none>"
|
||||
"checksum keccak-hash 0.1.0 (git+https://github.com/paritytech/parity.git)" = "<none>"
|
||||
"checksum keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f300c1f149cd9ca5214eed24f6e713a597517420fb8b15499824aa916259ec1"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
|
||||
"checksum lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9e5e58fa1a4c3b915a561a78a22ee0cac6ab97dca2504428bc1cb074375f8d5"
|
||||
"checksum lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "236eb37a62591d4a41a89b7763d7de3e06ca02d5ab2815446a8bae5d2f8c2d57"
|
||||
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
|
||||
"checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b"
|
||||
"checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2"
|
||||
"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
|
||||
"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
|
||||
"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
|
||||
"checksum memorydb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "013b7e4c5e10c764936ebc6bd3662d8e3c92292d267bf6a42ef3f5cad9c793ee"
|
||||
"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0"
|
||||
"checksum mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e00e17be181010a91dbfefb01660b17311059dc8c7f48b9017677721e732bd"
|
||||
"checksum mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0e8411968194c7b139e9105bc4ae7db0bae232af087147e72f0616ebf5fdb9cb"
|
||||
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
|
||||
@@ -1379,11 +1777,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "c3df9b730298cea3a1c3faa90b7e2f9df3a9c400d0936d6015e6165734eefcba"
|
||||
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
|
||||
"checksum parity-wasm 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)" = "235801e9531998c4bb307f4ea6833c9f40a4cf132895219ac8c2cd25a9b310f7"
|
||||
"checksum parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0dec124478845b142f68b446cbee953d14d4b41f1bc0425024417720dce693"
|
||||
"checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e"
|
||||
"checksum parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e7f7c9857874e54afeb950eebeae662b1e51a2493666d2ea4c0a5d91dcf0412"
|
||||
"checksum parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f610cb9664da38e417ea3225f23051f589851999535290e077939838ab7a595"
|
||||
"checksum path 0.1.0 (git+https://github.com/paritytech/parity.git)" = "<none>"
|
||||
"checksum patricia-trie 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e2f638d79aba5c4a71a4f373df6e3cd702250a53b7f0ed4da1e2a7be9737ae"
|
||||
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
|
||||
"checksum plain_hasher 0.1.0 (git+https://github.com/paritytech/parity.git)" = "<none>"
|
||||
"checksum plain_hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83ae80873992f511142c07d0ec6c44de5636628fdb7e204abd655932ea79d995"
|
||||
"checksum pretty_assertions 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94b6bbc8a323d89a019c4cdde21850522fb8405e97add70827177fc2f86c1495"
|
||||
"checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0"
|
||||
@@ -1398,27 +1799,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
|
||||
"checksum relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f301bafeb60867c85170031bdb2fcf24c8041f33aee09e7b116a58d4e9f781c5"
|
||||
"checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c"
|
||||
"checksum rlp 0.2.1 (git+https://github.com/paritytech/parity.git)" = "<none>"
|
||||
"checksum rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "babe6fce20c0ca9b1582998734c4569082d0ad08e43772a1c6c40aef4f106ef9"
|
||||
"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
|
||||
"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
|
||||
"checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e"
|
||||
"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
|
||||
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
||||
"checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69"
|
||||
"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f"
|
||||
"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
|
||||
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
|
||||
"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
|
||||
"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "0c9cab69e16835717c9b8bd13c29f92b6aa34fe32ce2866b1ab481cf2da8442a"
|
||||
"checksum serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "3bdafe3e71710131a919735916caa5b18c2754ad0d33d8ae5d586ccc804a403e"
|
||||
"checksum serde 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "5a2b181dd2b4a6353e828e44807269a761d3ecbc388a1f5ed3998ea69a516d9c"
|
||||
"checksum serde_derive 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "31ce3c16ec18abb97d977f75880986549213b0c18f2695eda8b31eadc96eda4a"
|
||||
"checksum serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1926285523b2db55df263d2aa4eb69ddcfa7a7eade6430323637866b513ab"
|
||||
"checksum serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e4586746d1974a030c48919731ecffd0ed28d0c40749d0d18d43b3a7d6c9b20e"
|
||||
"checksum slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6dbdd334bd28d328dad1c41b0ea662517883d8880d8533895ef96c8003dec9c4"
|
||||
"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
|
||||
"checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d"
|
||||
"checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013"
|
||||
"checksum smallvec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ee4f357e8cd37bf8822e1b964e96fd39e2cb5a0424f8aaa284ccaccc2162411c"
|
||||
"checksum snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)" = "<none>"
|
||||
"checksum snappy-sys 0.1.0 (git+https://github.com/paritytech/rust-snappy)" = "<none>"
|
||||
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
|
||||
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
|
||||
"checksum subtle 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b811576c12506ff3f6da145585dc833edc32ee34c9fc021127d90e8134cc05c"
|
||||
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
|
||||
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||
"checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5"
|
||||
@@ -1432,18 +1838,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fbb47ae81353c63c487030659494b295f6cb6576242f907f203473b191b0389"
|
||||
"checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162"
|
||||
"checksum tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6131e780037787ff1b3f8aad9da83bca02438b72277850dd6ad0d455e0e20efc"
|
||||
"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
|
||||
"checksum triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9291c7f0fae44858b5e087dd462afb382354120003778f1695b44aab98c7abd7"
|
||||
"checksum twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "475352206e7a290c5fccc27624a163e8d0d115f7bb60ca18a64fc9ce056d7435"
|
||||
"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
|
||||
"checksum uint 0.1.0 (git+https://github.com/paritytech/primitives.git)" = "<none>"
|
||||
"checksum unicase 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e01da42520092d0cd2d6ac3ae69eb21a22ad43ff195676b86f8c37f487d6b80"
|
||||
"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
|
||||
"checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a"
|
||||
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
|
||||
"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
|
||||
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
|
||||
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
|
||||
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
|
||||
"checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae"
|
||||
"checksum url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa35e768d4daf1d85733418a49fb42e10d7f633e394fccab4ab7aba897053fe2"
|
||||
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
|
||||
"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
|
||||
"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d"
|
||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
|
||||
"checksum xml-rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7ec6c39eaa68382c8e31e35239402c0a9489d4141a8ceb0c716099a0b515b562"
|
||||
"checksum xmltree 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "472a9d37c7c53ab2391161df5b89b1f3bf76dab6ab150d7941ecbdd832282082"
|
||||
"checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992"
|
||||
|
||||
@@ -6,6 +6,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
[dependencies]
|
||||
error-chain = "0.11"
|
||||
polkadot-cli = { path = "cli", version = "0.1" }
|
||||
polkadot-network = { path = "network" }
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
@@ -21,6 +22,7 @@ members = [
|
||||
"serializer",
|
||||
"state_machine",
|
||||
"validator",
|
||||
"network",
|
||||
]
|
||||
exclude = [
|
||||
"wasm-runtime"
|
||||
|
||||
@@ -16,9 +16,14 @@
|
||||
|
||||
//! Initialization errors.
|
||||
|
||||
use client;
|
||||
|
||||
error_chain! {
|
||||
foreign_links {
|
||||
Io(::std::io::Error) #[doc="IO error"];
|
||||
Cli(::clap::Error) #[doc="CLI error"];
|
||||
}
|
||||
links {
|
||||
Client(client::error::Error, client::error::ErrorKind) #[doc="Client error"];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,14 +48,13 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
|
||||
let yaml = load_yaml!("./cli.yml");
|
||||
let matches = clap::App::from_yaml(yaml).version(crate_version!()).get_matches_from_safe(args)?;
|
||||
|
||||
// TODO [ToDr] Split paremeters parsing from actual execution.
|
||||
// TODO [ToDr] Split parameters parsing from actual execution.
|
||||
let log_pattern = matches.value_of("log").unwrap_or("");
|
||||
init_logger(log_pattern);
|
||||
|
||||
// Create client
|
||||
let blockchain = DummyBlockchain;
|
||||
let executor = executor::executor();
|
||||
let client = client::Client::new(blockchain, executor);
|
||||
let client = client::new_in_mem(executor)?;
|
||||
|
||||
let address = "127.0.0.1:9933".parse().unwrap();
|
||||
let handler = rpc::rpc_handler(client);
|
||||
@@ -96,17 +95,3 @@ fn init_logger(pattern: &str) {
|
||||
builder.init().expect("Logger initialized only once.");
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct DummyBlockchain;
|
||||
|
||||
impl client::Blockchain for DummyBlockchain {
|
||||
type Error = ();
|
||||
|
||||
fn latest_hash(&self) -> Result<primitives::block::HeaderHash, Self::Error> {
|
||||
Ok(0.into())
|
||||
}
|
||||
|
||||
fn header(&self, _hash: &primitives::block::HeaderHash) -> Result<Option<primitives::block::Header>, Self::Error> {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,5 +5,8 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
error-chain = "0.11"
|
||||
log = "0.3"
|
||||
parking_lot = "0.4"
|
||||
polkadot-primitives = { path = "../primitives", version = "0.1" }
|
||||
polkadot-state-machine = { path = "../state_machine", version = "0.1" }
|
||||
polkadot-serializer = { path = "../serializer" }
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot 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.
|
||||
|
||||
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Polkadot Client data backend
|
||||
|
||||
use state_machine;
|
||||
use error;
|
||||
use primitives::block;
|
||||
use blockchain::{self, BlockId};
|
||||
|
||||
/// Block insertion transction. Keeps hold if the inseted block state and data.
|
||||
pub trait BlockImportOperation {
|
||||
/// Associated state backend type.
|
||||
type State: state_machine::backend::Backend;
|
||||
|
||||
/// Returns pending state.
|
||||
fn state(&self) -> error::Result<Self::State>;
|
||||
/// Append block data to the transaction.
|
||||
fn import_block(&mut self, header: block::Header, body: Option<block::Body>, is_new_best: bool) -> error::Result<()>;
|
||||
}
|
||||
|
||||
/// Client backend. Manages the data layer.
|
||||
pub trait Backend {
|
||||
/// Associated block insertion transaction type.
|
||||
type BlockImportOperation: BlockImportOperation;
|
||||
/// Associated blockchain backend type.
|
||||
type Blockchain: blockchain::Backend;
|
||||
/// Associated state backend type.
|
||||
type State: state_machine::backend::Backend;
|
||||
|
||||
/// Begin a new block insertion transaction with given parent block id.
|
||||
fn begin_transaction(&self, block: BlockId) -> error::Result<Self::BlockImportOperation>;
|
||||
/// Commit block insertion.
|
||||
fn commit_transaction(&self, transaction: Self::BlockImportOperation) -> error::Result<()>;
|
||||
/// Returns reference to blockchain backend.
|
||||
fn blockchain(&self) -> &Self::Blockchain;
|
||||
/// Returns state backend for specified block.
|
||||
fn state_at(&self, block: BlockId) -> error::Result<Self::State>;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot 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.
|
||||
|
||||
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Polkadot blockchain trait
|
||||
|
||||
use std::fmt::{Display, Formatter, Error as FmtError};
|
||||
use primitives::block;
|
||||
use error::Result;
|
||||
|
||||
/// Block indentification.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum BlockId {
|
||||
/// Identify by block header hash.
|
||||
Hash(block::HeaderHash),
|
||||
/// Identify by block number.
|
||||
Number(block::Number),
|
||||
}
|
||||
|
||||
impl Display for BlockId {
|
||||
fn fmt(&self, f: &mut Formatter) -> ::std::result::Result<(), FmtError> {
|
||||
match *self {
|
||||
BlockId::Hash(h) => h.fmt(f),
|
||||
BlockId::Number(n) => n.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Blockchain database backend. Does not perform any validation.
|
||||
pub trait Backend: Send + Sync {
|
||||
/// Get block header. Returns `None` if block is not found.
|
||||
fn header(&self, id: BlockId) -> Result<Option<block::Header>>;
|
||||
/// Get block body. Returns `None` if block is not found.
|
||||
fn body(&self, id: BlockId) -> Result<Option<block::Body>>;
|
||||
/// Get blockchain info.
|
||||
fn info(&self) -> Result<Info>;
|
||||
/// Get block status.
|
||||
fn status(&self, id: BlockId) -> Result<BlockStatus>;
|
||||
/// Get block hash by number. Returns `None` if the header is not in the chain.
|
||||
fn hash(&self, number: block::Number) -> Result<Option<block::HeaderHash>>;
|
||||
}
|
||||
|
||||
/// Block import outcome
|
||||
pub enum ImportResult<E> {
|
||||
/// Imported successfully.
|
||||
Imported,
|
||||
/// Block already exists, skippped.
|
||||
AlreadyInChain,
|
||||
/// Unknown parent.
|
||||
UnknownParent,
|
||||
/// Other errror.
|
||||
Err(E),
|
||||
}
|
||||
|
||||
/// Blockchain info
|
||||
#[derive(Debug)]
|
||||
pub struct Info {
|
||||
/// Best block hash.
|
||||
pub best_hash: block::HeaderHash,
|
||||
/// Best block number.
|
||||
pub best_number: block::Number,
|
||||
/// Genesis block hash.
|
||||
pub genesis_hash: block::HeaderHash,
|
||||
}
|
||||
|
||||
/// Block status.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum BlockStatus {
|
||||
/// Already in the blockchain.
|
||||
InChain,
|
||||
/// Not in the queue or the blockchain.
|
||||
Unknown,
|
||||
}
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
|
||||
//! Polkadot client possible errors.
|
||||
|
||||
use primitives::block;
|
||||
use std;
|
||||
use state_machine;
|
||||
use blockchain;
|
||||
|
||||
error_chain! {
|
||||
errors {
|
||||
@@ -28,7 +29,7 @@ error_chain! {
|
||||
}
|
||||
|
||||
/// Unknown block.
|
||||
UnknownBlock(h: block::HeaderHash) {
|
||||
UnknownBlock(h: blockchain::BlockId) {
|
||||
description("unknown block"),
|
||||
display("UnknownBlock: {}", h),
|
||||
}
|
||||
@@ -38,6 +39,12 @@ error_chain! {
|
||||
description("execution error"),
|
||||
display("Execution: {}", e),
|
||||
}
|
||||
|
||||
/// Blockchain error.
|
||||
Blockchain(e: Box<std::error::Error + Send>) {
|
||||
description("Blockchain error"),
|
||||
display("Blockchain: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,3 +54,16 @@ impl From<Box<state_machine::Error>> for Error {
|
||||
ErrorKind::Execution(e).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<state_machine::backend::Void> for Error {
|
||||
fn from(_e: state_machine::backend::Void) -> Self {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Error {
|
||||
/// Chain a blockchain error.
|
||||
pub fn from_blockchain(e: Box<std::error::Error + Send>) -> Self {
|
||||
ErrorKind::Blockchain(e).into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot 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.
|
||||
|
||||
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! In memory client backend
|
||||
|
||||
use std::collections::HashMap;
|
||||
use parking_lot::RwLock;
|
||||
use state_machine;
|
||||
use error;
|
||||
use backend;
|
||||
use primitives;
|
||||
use ser;
|
||||
use primitives::block::{self, HeaderHash};
|
||||
use blockchain::{self, BlockId, BlockStatus};
|
||||
|
||||
fn header_hash(header: &primitives::block::Header) -> primitives::block::HeaderHash {
|
||||
primitives::hash(&ser::to_vec(header))
|
||||
}
|
||||
|
||||
struct PendingBlock {
|
||||
block: Block,
|
||||
is_best: bool,
|
||||
}
|
||||
|
||||
struct Block {
|
||||
header: block::Header,
|
||||
body: Option<block::Body>,
|
||||
}
|
||||
|
||||
/// In-memory transaction.
|
||||
pub struct BlockImportOperation {
|
||||
pending_block: Option<PendingBlock>,
|
||||
pending_state: state_machine::backend::InMemory,
|
||||
}
|
||||
|
||||
struct BlockchainStorage {
|
||||
blocks: HashMap<HeaderHash, Block>,
|
||||
hashes: HashMap<block::Number, HeaderHash>,
|
||||
best_hash: HeaderHash,
|
||||
best_number: block::Number,
|
||||
genesis_hash: HeaderHash,
|
||||
}
|
||||
|
||||
/// In-memory blockchain. Supports concurrent reads.
|
||||
pub struct Blockchain {
|
||||
storage: RwLock<BlockchainStorage>,
|
||||
}
|
||||
|
||||
impl Blockchain {
|
||||
fn id(&self, id: BlockId) -> Option<HeaderHash> {
|
||||
match id {
|
||||
BlockId::Hash(h) => Some(h),
|
||||
BlockId::Number(n) => self.storage.read().hashes.get(&n).cloned(),
|
||||
}
|
||||
}
|
||||
|
||||
fn new() -> Blockchain {
|
||||
Blockchain {
|
||||
storage: RwLock::new(
|
||||
BlockchainStorage {
|
||||
blocks: HashMap::new(),
|
||||
hashes: HashMap::new(),
|
||||
best_hash: HeaderHash::default(),
|
||||
best_number: 0,
|
||||
genesis_hash: HeaderHash::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn insert(&self, hash: HeaderHash, header: block::Header, body: Option<block::Body>, is_new_best: bool) {
|
||||
let number = header.number;
|
||||
let mut storage = self.storage.write();
|
||||
storage.blocks.insert(hash, Block {
|
||||
header: header,
|
||||
body: body,
|
||||
});
|
||||
storage.hashes.insert(number, hash);
|
||||
if is_new_best {
|
||||
storage.best_hash = hash;
|
||||
storage.best_number = number;
|
||||
}
|
||||
if number == 0 {
|
||||
storage.genesis_hash = hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl blockchain::Backend for Blockchain {
|
||||
fn header(&self, id: BlockId) -> error::Result<Option<block::Header>> {
|
||||
Ok(self.id(id).and_then(|hash| self.storage.read().blocks.get(&hash).map(|b| b.header.clone())))
|
||||
}
|
||||
|
||||
fn body(&self, id: BlockId) -> error::Result<Option<block::Body>> {
|
||||
Ok(self.id(id).and_then(|hash| self.storage.read().blocks.get(&hash).and_then(|b| b.body.clone())))
|
||||
}
|
||||
|
||||
fn info(&self) -> error::Result<blockchain::Info> {
|
||||
let storage = self.storage.read();
|
||||
Ok(blockchain::Info {
|
||||
best_hash: storage.best_hash,
|
||||
best_number: storage.best_number,
|
||||
genesis_hash: storage.genesis_hash,
|
||||
})
|
||||
}
|
||||
|
||||
fn status(&self, id: BlockId) -> error::Result<BlockStatus> {
|
||||
match self.id(id).map_or(false, |hash| self.storage.read().blocks.contains_key(&hash)) {
|
||||
true => Ok(BlockStatus::InChain),
|
||||
false => Ok(BlockStatus::Unknown),
|
||||
}
|
||||
}
|
||||
|
||||
fn hash(&self, number: block::Number) -> error::Result<Option<block::HeaderHash>> {
|
||||
Ok(self.id(BlockId::Number(number)))
|
||||
}
|
||||
}
|
||||
|
||||
impl backend::BlockImportOperation for BlockImportOperation {
|
||||
type State = state_machine::backend::InMemory;
|
||||
|
||||
fn state(&self) -> error::Result<Self::State> {
|
||||
Ok(self.pending_state.clone())
|
||||
}
|
||||
|
||||
fn import_block(&mut self, header: block::Header, body: Option<block::Body>, is_new_best: bool) -> error::Result<()> {
|
||||
assert!(self.pending_block.is_none(), "Only one block per transaction is allowed");
|
||||
self.pending_block = Some(PendingBlock {
|
||||
block: Block {
|
||||
header: header,
|
||||
body: body,
|
||||
},
|
||||
is_best: is_new_best,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// In-memory backend. Keeps all states and blocks in memory. Useful for testing.
|
||||
pub struct Backend {
|
||||
states: RwLock<HashMap<block::HeaderHash, state_machine::backend::InMemory>>,
|
||||
blockchain: Blockchain,
|
||||
}
|
||||
|
||||
impl Backend {
|
||||
/// Create a new instance of in-mem backend.
|
||||
pub fn new() -> Backend {
|
||||
Backend {
|
||||
states: RwLock::new(HashMap::new()),
|
||||
blockchain: Blockchain::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl backend::Backend for Backend {
|
||||
type BlockImportOperation = BlockImportOperation;
|
||||
type Blockchain = Blockchain;
|
||||
type State = state_machine::backend::InMemory;
|
||||
|
||||
fn begin_transaction(&self, block: BlockId) -> error::Result<Self::BlockImportOperation> {
|
||||
let state = match block {
|
||||
BlockId::Hash(h) if h.is_zero() => Self::State::default(),
|
||||
_ => self.state_at(block)?,
|
||||
};
|
||||
|
||||
Ok(BlockImportOperation {
|
||||
pending_block: None,
|
||||
pending_state: state,
|
||||
})
|
||||
}
|
||||
|
||||
fn commit_transaction(&self, transaction: Self::BlockImportOperation) -> error::Result<()> {
|
||||
if let Some(pending_block) = transaction.pending_block {
|
||||
let hash = header_hash(&pending_block.block.header);
|
||||
self.states.write().insert(hash, transaction.pending_state);
|
||||
self.blockchain.insert(hash, pending_block.block.header, pending_block.block.body, pending_block.is_best);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn blockchain(&self) -> &Blockchain {
|
||||
&self.blockchain
|
||||
}
|
||||
|
||||
fn state_at(&self, block: BlockId) -> error::Result<Self::State> {
|
||||
match self.blockchain.id(block).and_then(|id| self.states.read().get(&id).cloned()) {
|
||||
Some(state) => Ok(state),
|
||||
None => Err(error::ErrorKind::UnknownBlock(block).into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+133
-32
@@ -20,28 +20,43 @@
|
||||
|
||||
extern crate polkadot_primitives as primitives;
|
||||
extern crate polkadot_state_machine as state_machine;
|
||||
extern crate polkadot_serializer as ser;
|
||||
|
||||
#[macro_use]
|
||||
extern crate error_chain;
|
||||
extern crate parking_lot;
|
||||
#[macro_use] extern crate error_chain;
|
||||
#[macro_use] extern crate log;
|
||||
|
||||
pub mod error;
|
||||
pub mod blockchain;
|
||||
pub mod backend;
|
||||
pub mod in_mem;
|
||||
|
||||
pub use blockchain::Info as ChainInfo;
|
||||
pub use blockchain::BlockId;
|
||||
|
||||
use primitives::{block};
|
||||
use primitives::contract::{CallData, StorageKey, StorageData};
|
||||
use state_machine::backend::Backend;
|
||||
|
||||
use self::error::ResultExt;
|
||||
use blockchain::Backend as BlockchainBackend;
|
||||
use backend::BlockImportOperation;
|
||||
use state_machine::backend::Backend as StateBackend;
|
||||
|
||||
/// Blockchain access
|
||||
pub trait Blockchain {
|
||||
/// Error Type
|
||||
type Error;
|
||||
/// Polkadot Client
|
||||
#[derive(Debug)]
|
||||
pub struct Client<B, E> where B: backend::Backend {
|
||||
backend: B,
|
||||
executor: E,
|
||||
}
|
||||
|
||||
/// Returns the hash of latest block.
|
||||
fn latest_hash(&self) -> Result<block::HeaderHash, Self::Error>;
|
||||
|
||||
/// Given a hash return a header
|
||||
fn header(&self, hash: &block::HeaderHash) -> Result<Option<block::Header>, Self::Error>;
|
||||
/// Client info
|
||||
#[derive(Debug)]
|
||||
pub struct ClientInfo {
|
||||
/// Best block hash.
|
||||
pub chain: ChainInfo,
|
||||
/// Best block number in the queue.
|
||||
pub best_queued_number: Option<block::Number>,
|
||||
/// Best queued block hash.
|
||||
pub best_queued_hash: Option<block::HeaderHash>,
|
||||
}
|
||||
|
||||
/// Information regarding the result of a call.
|
||||
@@ -52,39 +67,77 @@ pub struct CallResult {
|
||||
pub changes: state_machine::OverlayedChanges,
|
||||
}
|
||||
|
||||
/// Polkadot Client
|
||||
/// Block import result.
|
||||
#[derive(Debug)]
|
||||
pub struct Client<B, E> {
|
||||
blockchain: B,
|
||||
executor: E,
|
||||
pub enum ImportResult {
|
||||
/// Added to the import queue.
|
||||
Queued,
|
||||
/// Already in the import queue.
|
||||
AlreadyQueued,
|
||||
/// Already in the blockchain.
|
||||
AlreadyInChain,
|
||||
/// Block or parent is known to be bad.
|
||||
KnownBad,
|
||||
/// Block parent is not in the chain.
|
||||
UnknownParent,
|
||||
}
|
||||
|
||||
impl<B, E> Client<B, E> {
|
||||
/// Creates new Polkadot Client with given blockchain and code executor.
|
||||
pub fn new(blockchain: B, executor: E) -> Self {
|
||||
Client {
|
||||
blockchain,
|
||||
executor,
|
||||
}
|
||||
}
|
||||
/// Block status.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum BlockStatus {
|
||||
/// Added to the import queue.
|
||||
Queued,
|
||||
/// Already in the blockchain.
|
||||
InChain,
|
||||
/// Block or parent is known to be bad.
|
||||
KnownBad,
|
||||
/// Not in the queue or the blockchain.
|
||||
Unknown,
|
||||
}
|
||||
|
||||
|
||||
/// Create an instance of in-memory client.
|
||||
pub fn new_in_mem<E>(executor: E) -> error::Result<Client<in_mem::Backend, E>> where E: state_machine::CodeExecutor {
|
||||
Client::new(in_mem::Backend::new(), executor)
|
||||
}
|
||||
|
||||
impl<B, E> Client<B, E> where
|
||||
B: Blockchain,
|
||||
B: backend::Backend,
|
||||
E: state_machine::CodeExecutor,
|
||||
error::Error: From<<<B as backend::Backend>::State as state_machine::backend::Backend>::Error>,
|
||||
{
|
||||
/// Creates new Polkadot Client with given blockchain and code executor.
|
||||
pub fn new(backend: B, executor: E) -> error::Result<Self> {
|
||||
if backend.blockchain().header(BlockId::Number(0))?.is_none() {
|
||||
trace!("Empty database, writing genesis block");
|
||||
// TODO: spec
|
||||
let genesis_header = block::Header {
|
||||
parent_hash: Default::default(),
|
||||
number: 0,
|
||||
state_root: Default::default(),
|
||||
parachain_activity: Default::default(),
|
||||
logs: Default::default(),
|
||||
};
|
||||
|
||||
fn state_at(&self, _hash: &block::HeaderHash) -> error::Result<state_machine::backend::InMemory> {
|
||||
// TODO [ToDr] Actually retrieve the state.
|
||||
Ok(state_machine::backend::InMemory::default())
|
||||
let mut tx = backend.begin_transaction(BlockId::Hash(block::HeaderHash::default()))?;
|
||||
tx.import_block(genesis_header, None, true)?;
|
||||
backend.commit_transaction(tx)?;
|
||||
}
|
||||
Ok(Client {
|
||||
backend,
|
||||
executor,
|
||||
})
|
||||
}
|
||||
|
||||
fn state_at(&self, hash: &block::HeaderHash) -> error::Result<B::State> {
|
||||
self.backend.state_at(BlockId::Hash(*hash))
|
||||
}
|
||||
|
||||
/// Return single storage entry of contract under given address in state in a block of given hash.
|
||||
pub fn storage(&self, hash: &block::HeaderHash, key: &StorageKey) -> error::Result<StorageData> {
|
||||
self.state_at(hash)?
|
||||
Ok(self.state_at(hash)?
|
||||
.storage(&key.0)
|
||||
.map(|x| StorageData(x.to_vec()))
|
||||
.chain_err(|| error::ErrorKind::Backend)
|
||||
.map(|x| StorageData(x.to_vec()))?)
|
||||
}
|
||||
|
||||
/// Execute a call to a contract on top of state in a block of given hash.
|
||||
@@ -103,4 +156,52 @@ impl<B, E> Client<B, E> where
|
||||
)?;
|
||||
Ok(CallResult { return_data: vec![], changes })
|
||||
}
|
||||
|
||||
/// Queue a block for import.
|
||||
pub fn import_block(&self, header: block::Header, body: Option<block::Body>) -> error::Result<ImportResult> {
|
||||
// TODO: import lock
|
||||
// TODO: validate block
|
||||
match self.backend.blockchain().status(BlockId::Hash(header.parent_hash))? {
|
||||
blockchain::BlockStatus::InChain => (),
|
||||
blockchain::BlockStatus::Unknown => return Ok(ImportResult::UnknownParent),
|
||||
}
|
||||
|
||||
let mut transaction = self.backend.begin_transaction(BlockId::Number(header.number))?;
|
||||
let mut _state = transaction.state()?;
|
||||
// TODO: execute block on _state
|
||||
|
||||
let is_new_best = header.number == self.backend.blockchain().info()?.best_number + 1;
|
||||
transaction.import_block(header, body, is_new_best)?;
|
||||
self.backend.commit_transaction(transaction)?;
|
||||
Ok(ImportResult::Queued)
|
||||
}
|
||||
|
||||
/// Get blockchain info.
|
||||
pub fn info(&self) -> error::Result<ClientInfo> {
|
||||
let info = self.backend.blockchain().info().map_err(|e| error::Error::from_blockchain(Box::new(e)))?;
|
||||
Ok(ClientInfo {
|
||||
chain: info,
|
||||
best_queued_hash: None,
|
||||
best_queued_number: None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Get block status.
|
||||
pub fn block_status(&self, hash: &block::HeaderHash) -> error::Result<BlockStatus> {
|
||||
// TODO: more efficient implementation
|
||||
match self.backend.blockchain().header(BlockId::Hash(*hash)).map_err(|e| error::Error::from_blockchain(Box::new(e)))?.is_some() {
|
||||
true => Ok(BlockStatus::InChain),
|
||||
false => Ok(BlockStatus::Unknown),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get block hash by number.
|
||||
pub fn block_hash(&self, block_number: block::Number) -> error::Result<Option<block::HeaderHash>> {
|
||||
self.backend.blockchain().hash(block_number)
|
||||
}
|
||||
|
||||
/// Get block header by hash.
|
||||
pub fn header(&self, hash: &block::HeaderHash) -> error::Result<Option<block::Header>> {
|
||||
self.backend.blockchain().header(BlockId::Hash(*hash))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
[package]
|
||||
description = "Polkadot network protocol"
|
||||
name = "polkadot-network"
|
||||
version = "0.1.0"
|
||||
license = "GPL-3.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[lib]
|
||||
|
||||
[dependencies]
|
||||
ethcore-network = { git = "https://github.com/paritytech/parity.git" }
|
||||
ethcore-io = { git = "https://github.com/paritytech/parity.git" }
|
||||
polkadot-primitives = { path = "../primitives" }
|
||||
polkadot-client = { path = "../client" }
|
||||
polkadot-state-machine = { path = "../state_machine" }
|
||||
polkadot-serializer = { path = "../serializer" }
|
||||
log = "0.3"
|
||||
env_logger = "0.4"
|
||||
rand = "0.3"
|
||||
heapsize = "0.4"
|
||||
semver = "0.6"
|
||||
smallvec = { version = "0.4", features = ["heapsizeof"] }
|
||||
parking_lot = "0.4"
|
||||
ipnetwork = "0.12"
|
||||
error-chain = "0.11"
|
||||
bitflags = "1.0"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0"
|
||||
@@ -0,0 +1,263 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot 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.
|
||||
|
||||
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.?
|
||||
|
||||
use std::mem;
|
||||
use std::cmp;
|
||||
use std::ops::Range;
|
||||
use std::collections::{HashMap, BTreeMap};
|
||||
use std::collections::hash_map::Entry;
|
||||
use network::PeerId;
|
||||
use primitives::block::{Number as BlockNumber};
|
||||
use message;
|
||||
|
||||
const MAX_PARALLEL_DOWNLOADS: u32 = 1;
|
||||
|
||||
/// Block data with origin.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct BlockData {
|
||||
pub block: message::BlockData,
|
||||
pub origin: PeerId,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum BlockRangeState {
|
||||
Downloading {
|
||||
len: BlockNumber,
|
||||
downloading: u32,
|
||||
},
|
||||
Complete(Vec<BlockData>),
|
||||
}
|
||||
|
||||
impl BlockRangeState {
|
||||
pub fn len(&self) -> BlockNumber {
|
||||
match *self {
|
||||
BlockRangeState::Downloading { len, .. } => len,
|
||||
BlockRangeState::Complete(ref blocks) => blocks.len() as BlockNumber,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A collection of blocks being downloaded.
|
||||
#[derive(Default)]
|
||||
pub struct BlockCollection {
|
||||
/// Downloaded blocks.
|
||||
blocks: BTreeMap<BlockNumber, BlockRangeState>,
|
||||
peer_requests: HashMap<PeerId, BlockNumber>,
|
||||
}
|
||||
|
||||
impl BlockCollection {
|
||||
/// Create a new instance.
|
||||
pub fn new() -> BlockCollection {
|
||||
BlockCollection {
|
||||
blocks: BTreeMap::new(),
|
||||
peer_requests: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Clear everything.
|
||||
pub fn clear(&mut self) {
|
||||
self.blocks.clear();
|
||||
self.peer_requests.clear();
|
||||
}
|
||||
|
||||
/// Insert a set of blocks into collection.
|
||||
pub fn insert(&mut self, start: BlockNumber, blocks: Vec<message::BlockData>, peer_id: PeerId) {
|
||||
if blocks.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
match self.blocks.get(&start) {
|
||||
Some(&BlockRangeState::Downloading { .. }) => {
|
||||
trace!(target: "sync", "Ignored block data still marked as being downloaded: {}", start);
|
||||
debug_assert!(false);
|
||||
return;
|
||||
},
|
||||
Some(&BlockRangeState::Complete(ref existing)) if existing.len() >= blocks.len() => {
|
||||
trace!(target: "sync", "Ignored block data already downloaded: {}", start);
|
||||
return;
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
|
||||
self.blocks.insert(start, BlockRangeState::Complete(blocks.into_iter().map(|b| BlockData { origin: peer_id, block: b }).collect()));
|
||||
}
|
||||
|
||||
/// Returns a set of block hashes that require a header download. The returned set is marked as being downloaded.
|
||||
pub fn needed_blocks(&mut self, peer_id: PeerId, count: usize, peer_best: BlockNumber, common: BlockNumber) -> Option<Range<BlockNumber>> {
|
||||
// First block number that we need to download
|
||||
let first_different = common + 1;
|
||||
let count = count as BlockNumber;
|
||||
let (mut range, downloading) = {
|
||||
let mut downloading_iter = self.blocks.iter().peekable();
|
||||
let mut prev: Option<(&BlockNumber, &BlockRangeState)> = None;
|
||||
loop {
|
||||
let next = downloading_iter.next();
|
||||
break match &(prev, next) {
|
||||
&(Some((start, &BlockRangeState::Downloading { ref len, downloading })), _) if downloading < MAX_PARALLEL_DOWNLOADS =>
|
||||
(*start .. *start + *len, downloading),
|
||||
&(Some((start, r)), Some((next_start, _))) if start + r.len() < *next_start =>
|
||||
(*start + r.len() .. cmp::min(*next_start, *start + count), 0), // gap
|
||||
&(Some((start, r)), None) =>
|
||||
(start + r.len() .. start + r.len() + count, 0), // last range
|
||||
&(None, None) =>
|
||||
(first_different .. first_different + count, 0), // empty
|
||||
&(None, Some((start, _))) if *start > first_different =>
|
||||
(first_different .. cmp::min(first_different + count, *start), 0), // gap at the start
|
||||
_ => {
|
||||
prev = next;
|
||||
continue
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// crop to peers best
|
||||
if range.start >= peer_best {
|
||||
return None;
|
||||
}
|
||||
range.end = cmp::min(peer_best, range.end);
|
||||
|
||||
self.peer_requests.insert(peer_id, range.start);
|
||||
self.blocks.insert(range.start, BlockRangeState::Downloading{ len: range.end - range.start, downloading: downloading + 1 });
|
||||
Some(range)
|
||||
}
|
||||
|
||||
/// Get a valid chain of blocks ordered in descending order and ready for importing into blockchain.
|
||||
pub fn drain(&mut self, from: BlockNumber) -> Vec<BlockData> {
|
||||
let mut drained = Vec::new();
|
||||
let mut ranges = Vec::new();
|
||||
{
|
||||
let mut prev = from;
|
||||
for (start, range_data) in &mut self.blocks {
|
||||
match range_data {
|
||||
&mut BlockRangeState::Complete(ref mut blocks) if *start <= prev => {
|
||||
prev = *start + blocks.len() as BlockNumber;
|
||||
let mut blocks = mem::replace(blocks, Vec::new());
|
||||
drained.append(&mut blocks);
|
||||
ranges.push(*start);
|
||||
},
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
for r in ranges {
|
||||
self.blocks.remove(&r);
|
||||
}
|
||||
trace!(target: "sync", "Drained {} blocks", drained.len());
|
||||
drained
|
||||
}
|
||||
|
||||
pub fn clear_peer_download(&mut self, peer_id: PeerId) {
|
||||
match self.peer_requests.entry(peer_id) {
|
||||
Entry::Occupied(entry) => {
|
||||
let start = entry.remove();
|
||||
let remove = match self.blocks.get_mut(&start) {
|
||||
Some(&mut BlockRangeState::Downloading { ref mut downloading, .. }) if *downloading > 1 => {
|
||||
*downloading = *downloading - 1;
|
||||
false
|
||||
},
|
||||
Some(&mut BlockRangeState::Downloading { .. }) => {
|
||||
true
|
||||
},
|
||||
_ => {
|
||||
debug_assert!(false);
|
||||
false
|
||||
}
|
||||
};
|
||||
if remove {
|
||||
self.blocks.remove(&start);
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{BlockCollection, BlockData};
|
||||
use message;
|
||||
use primitives::block::{HeaderHash};
|
||||
|
||||
fn is_empty(bc: &BlockCollection) -> bool {
|
||||
bc.blocks.is_empty() &&
|
||||
bc.peer_requests.is_empty()
|
||||
}
|
||||
|
||||
fn generate_blocks(n: usize) -> Vec<message::BlockData> {
|
||||
(0 .. n).map(|_| message::BlockData {
|
||||
hash: HeaderHash::random(),
|
||||
header: None,
|
||||
body: None,
|
||||
message_queue: None,
|
||||
receipt: None,
|
||||
}).collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_clear() {
|
||||
let mut bc = BlockCollection::new();
|
||||
assert!(is_empty(&bc));
|
||||
bc.insert(1, generate_blocks(100), 0);
|
||||
assert!(!is_empty(&bc));
|
||||
bc.clear();
|
||||
assert!(is_empty(&bc));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_blocks() {
|
||||
let mut bc = BlockCollection::new();
|
||||
assert!(is_empty(&bc));
|
||||
let peer0 = 0;
|
||||
let peer1 = 1;
|
||||
let peer2 = 2;
|
||||
|
||||
let blocks = generate_blocks(150);
|
||||
assert_eq!(bc.needed_blocks(peer0, 40, 150, 0), Some(1 .. 41));
|
||||
assert_eq!(bc.needed_blocks(peer1, 40, 150, 0), Some(41 .. 81));
|
||||
assert_eq!(bc.needed_blocks(peer2, 40, 150, 0), Some(81 .. 121));
|
||||
|
||||
bc.clear_peer_download(peer1);
|
||||
bc.insert(41, blocks[41..81].to_vec(), peer1);
|
||||
assert_eq!(bc.drain(1), vec![]);
|
||||
assert_eq!(bc.needed_blocks(peer1, 40, 150, 0), Some(121 .. 150));
|
||||
bc.clear_peer_download(peer0);
|
||||
bc.insert(1, blocks[1..11].to_vec(), peer0);
|
||||
|
||||
assert_eq!(bc.needed_blocks(peer0, 40, 150, 0), Some(11 .. 41));
|
||||
assert_eq!(bc.drain(1), blocks[1..11].iter().map(|b| BlockData { block: b.clone(), origin: 0 }).collect::<Vec<_>>());
|
||||
|
||||
bc.clear_peer_download(peer0);
|
||||
bc.insert(11, blocks[11..41].to_vec(), peer0);
|
||||
|
||||
let drained = bc.drain(12);
|
||||
assert_eq!(drained[..30], blocks[11..41].iter().map(|b| BlockData { block: b.clone(), origin: 0 }).collect::<Vec<_>>()[..]);
|
||||
assert_eq!(drained[30..], blocks[41..81].iter().map(|b| BlockData { block: b.clone(), origin: 1 }).collect::<Vec<_>>()[..]);
|
||||
|
||||
bc.clear_peer_download(peer2);
|
||||
assert_eq!(bc.needed_blocks(peer2, 40, 150, 80), Some(81 .. 121));
|
||||
bc.clear_peer_download(peer2);
|
||||
bc.insert(81, blocks[81..121].to_vec(), peer2);
|
||||
bc.clear_peer_download(peer1);
|
||||
bc.insert(121, blocks[121..150].to_vec(), peer1);
|
||||
|
||||
assert_eq!(bc.drain(80), vec![]);
|
||||
let drained = bc.drain(81);
|
||||
assert_eq!(drained[..40], blocks[81..121].iter().map(|b| BlockData { block: b.clone(), origin: 2 }).collect::<Vec<_>>()[..]);
|
||||
assert_eq!(drained[40..], blocks[121..150].iter().map(|b| BlockData { block: b.clone(), origin: 1 }).collect::<Vec<_>>()[..]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot 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.
|
||||
|
||||
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Blockchain access trait
|
||||
|
||||
use client::{self, Client as PolkadotClient, ImportResult, ClientInfo, BlockStatus};
|
||||
use client::error::Error;
|
||||
use state_machine;
|
||||
use primitives::block;
|
||||
|
||||
pub trait Client : Send + Sync {
|
||||
/// Given a hash return a header
|
||||
fn import(&self, header: block::Header, body: Option<block::Body>) -> Result<ImportResult, Error>;
|
||||
|
||||
/// Get blockchain info.
|
||||
fn info(&self) -> Result<ClientInfo, Error>;
|
||||
|
||||
/// Get block status.
|
||||
fn block_status(&self, hash: &block::HeaderHash) -> Result<BlockStatus, Error>;
|
||||
|
||||
/// Get block hash by number.
|
||||
fn block_hash(&self, block_number: block::Number) -> Result<Option<block::HeaderHash>, Error>;
|
||||
}
|
||||
|
||||
impl<B, E> Client for PolkadotClient<B, E> where
|
||||
B: client::backend::Backend + Send + Sync + 'static,
|
||||
E: state_machine::CodeExecutor + Send + Sync + 'static,
|
||||
{
|
||||
fn import(&self, header: block::Header, body: Option<block::Body>) -> Result<ImportResult, Error> {
|
||||
(self as &Client).import(header, body)
|
||||
}
|
||||
|
||||
fn info(&self) -> Result<ClientInfo, Error> {
|
||||
(self as &Client).info()
|
||||
}
|
||||
|
||||
fn block_status(&self, hash: &block::HeaderHash) -> Result<BlockStatus, Error> {
|
||||
(self as &Client).block_status(hash)
|
||||
}
|
||||
|
||||
fn block_hash(&self, block_number: block::Number) -> Result<Option<block::HeaderHash>, Error> {
|
||||
(self as &Client).block_hash(block_number)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot 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.
|
||||
|
||||
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.?
|
||||
|
||||
use service::Role;
|
||||
|
||||
/// Protocol configuration
|
||||
pub struct ProtocolConfig {
|
||||
pub roles: Role,
|
||||
}
|
||||
|
||||
impl Default for ProtocolConfig {
|
||||
fn default() -> ProtocolConfig {
|
||||
ProtocolConfig {
|
||||
roles: Role::FULL,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,34 +12,20 @@
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.?
|
||||
|
||||
use network::Error as NetworkError;
|
||||
use client;
|
||||
use primitives::{block, parachain};
|
||||
|
||||
/// Temporary dummy blockchain implementation for tests.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Blockchain;
|
||||
|
||||
impl client::Blockchain for Blockchain {
|
||||
type Error = ::std::io::Error;
|
||||
|
||||
fn latest_hash(&self) -> Result<block::HeaderHash, Self::Error> {
|
||||
Ok(0.into())
|
||||
error_chain! {
|
||||
foreign_links {
|
||||
Network(NetworkError) #[doc = "Devp2p error."];
|
||||
}
|
||||
|
||||
fn header(&self, hash: &block::HeaderHash) -> Result<Option<block::Header>, Self::Error> {
|
||||
Ok(if hash != &0.into() {
|
||||
None
|
||||
} else {
|
||||
Some(block::Header {
|
||||
parent_hash: 0.into(),
|
||||
number: 0,
|
||||
state_root: 0.into(),
|
||||
parachain_activity: parachain::Activity(vec![0]),
|
||||
logs: vec![],
|
||||
})
|
||||
})
|
||||
links {
|
||||
Client(client::error::Error, client::error::ErrorKind);
|
||||
}
|
||||
|
||||
errors {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot 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.
|
||||
|
||||
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.?
|
||||
|
||||
use network::{NetworkContext, PeerId, Error as NetworkError, SessionInfo};
|
||||
|
||||
/// IO interface for the syncing handler.
|
||||
/// Provides peer connection management and an interface to the blockchain client.
|
||||
pub trait SyncIo {
|
||||
/// Disable a peer
|
||||
fn disable_peer(&mut self, peer_id: PeerId);
|
||||
/// Disconnect peer
|
||||
fn disconnect_peer(&mut self, peer_id: PeerId);
|
||||
/// Send a packet to a peer.
|
||||
fn send(&mut self, peer_id: PeerId, data: Vec<u8>) -> Result<(), NetworkError>;
|
||||
/// Returns peer identifier string
|
||||
fn peer_info(&self, peer_id: PeerId) -> String {
|
||||
peer_id.to_string()
|
||||
}
|
||||
/// Returns information on p2p session
|
||||
fn peer_session_info(&self, peer_id: PeerId) -> Option<SessionInfo>;
|
||||
/// Check if the session is expired
|
||||
fn is_expired(&self) -> bool;
|
||||
}
|
||||
|
||||
/// Wraps `NetworkContext` and the blockchain client
|
||||
pub struct NetSyncIo<'s, 'h> where 'h: 's {
|
||||
network: &'s NetworkContext<'h>,
|
||||
}
|
||||
|
||||
impl<'s, 'h> NetSyncIo<'s, 'h> {
|
||||
/// Creates a new instance from the `NetworkContext` and the blockchain client reference.
|
||||
pub fn new(network: &'s NetworkContext<'h>) -> NetSyncIo<'s, 'h> {
|
||||
NetSyncIo {
|
||||
network: network,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, 'h> SyncIo for NetSyncIo<'s, 'h> {
|
||||
fn disable_peer(&mut self, peer_id: PeerId) {
|
||||
self.network.disable_peer(peer_id);
|
||||
}
|
||||
|
||||
fn disconnect_peer(&mut self, peer_id: PeerId) {
|
||||
self.network.disconnect_peer(peer_id);
|
||||
}
|
||||
|
||||
fn send(&mut self, peer_id: PeerId, data: Vec<u8>) -> Result<(), NetworkError>{
|
||||
self.network.send(peer_id, 0, data)
|
||||
}
|
||||
|
||||
fn peer_session_info(&self, peer_id: PeerId) -> Option<SessionInfo> {
|
||||
self.network.session_info(peer_id)
|
||||
}
|
||||
|
||||
fn is_expired(&self) -> bool {
|
||||
self.network.is_expired()
|
||||
}
|
||||
|
||||
fn peer_info(&self, peer_id: PeerId) -> String {
|
||||
self.network.peer_client_version(peer_id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot 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.
|
||||
|
||||
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.?
|
||||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
//! Implements polkadot protocol version as specified here:
|
||||
//! https://github.com/paritytech/polkadot/wiki/Network-protocol
|
||||
|
||||
extern crate ethcore_network as network;
|
||||
extern crate ethcore_io as core_io;
|
||||
extern crate env_logger;
|
||||
extern crate rand;
|
||||
extern crate semver;
|
||||
extern crate parking_lot;
|
||||
extern crate smallvec;
|
||||
extern crate ipnetwork;
|
||||
extern crate polkadot_primitives as primitives;
|
||||
extern crate polkadot_client as client;
|
||||
extern crate polkadot_state_machine as state_machine;
|
||||
extern crate polkadot_serializer as ser;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
#[macro_use] extern crate serde_derive;
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use] extern crate bitflags;
|
||||
#[macro_use] extern crate error_chain;
|
||||
|
||||
mod service;
|
||||
mod sync;
|
||||
mod protocol;
|
||||
mod io;
|
||||
mod message;
|
||||
mod error;
|
||||
mod config;
|
||||
mod chain;
|
||||
mod blocks;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
||||
pub use service::Service;
|
||||
pub use protocol::{ProtocolStatus};
|
||||
pub use network::{NonReservedPeerMode, ConnectionFilter, ConnectionDirection, NetworkConfiguration};
|
||||
|
||||
// TODO: move it elsewhere
|
||||
fn header_hash(header: &primitives::block::Header) -> primitives::block::HeaderHash {
|
||||
primitives::hash(&ser::to_vec(header))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot 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.
|
||||
|
||||
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.?
|
||||
|
||||
//! Network packet message types. These get serialized and put into the lower level protocol payload.
|
||||
|
||||
use std::borrow::Borrow;
|
||||
use primitives::parachain::Id as ParachainId;
|
||||
use primitives::Address;
|
||||
use primitives::block::{Number as BlockNumber, HeaderHash, Header, Body};
|
||||
use service::Role as RoleFlags;
|
||||
|
||||
pub type RequestId = u64;
|
||||
type Bytes = Vec<u8>;
|
||||
|
||||
type Signature = ::primitives::hash::H256; //TODO:
|
||||
|
||||
/// Configured node role.
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Role {
|
||||
/// Full relay chain client with no additional responsibilities.
|
||||
Full,
|
||||
/// Relay chain light client.
|
||||
Light,
|
||||
/// Parachain validator.
|
||||
Validator,
|
||||
/// Parachain collator.
|
||||
Collator,
|
||||
}
|
||||
|
||||
impl<T> From<T> for RoleFlags where T: Borrow<[Role]> {
|
||||
fn from(roles: T) -> RoleFlags {
|
||||
let mut flags = RoleFlags::NONE;
|
||||
let roles: &[Role] = roles.borrow();
|
||||
for r in roles {
|
||||
match *r {
|
||||
Role::Full => flags = flags | RoleFlags::FULL,
|
||||
Role::Light => flags = flags | RoleFlags::LIGHT,
|
||||
Role::Validator => flags = flags | RoleFlags::VALIDATOR,
|
||||
Role::Collator => flags = flags | RoleFlags::COLLATOR,
|
||||
}
|
||||
}
|
||||
flags
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RoleFlags> for Vec<Role> where {
|
||||
fn from(flags: RoleFlags) -> Vec<Role> {
|
||||
let mut roles = Vec::new();
|
||||
if !(flags & RoleFlags::FULL).is_empty() {
|
||||
roles.push(Role::Full);
|
||||
}
|
||||
if !(flags & RoleFlags::LIGHT).is_empty() {
|
||||
roles.push(Role::Light);
|
||||
}
|
||||
if !(flags & RoleFlags::VALIDATOR).is_empty() {
|
||||
roles.push(Role::Validator);
|
||||
}
|
||||
if !(flags & RoleFlags::COLLATOR).is_empty() {
|
||||
roles.push(Role::Collator);
|
||||
}
|
||||
roles
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Copy, Clone)]
|
||||
/// Bits of block data and associated artefacts to request.
|
||||
pub enum BlockAttribute {
|
||||
/// Include block header.
|
||||
Header,
|
||||
/// Include block body.
|
||||
Body,
|
||||
/// Include block receipt.
|
||||
Receipt,
|
||||
/// Include block message queue.
|
||||
MessageQueue,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
/// Block data sent in the response.
|
||||
pub struct BlockData {
|
||||
/// Block header hash.
|
||||
pub hash: HeaderHash,
|
||||
/// Block header if requested.
|
||||
pub header: Option<Header>,
|
||||
/// Block body if requested.
|
||||
pub body: Option<Body>,
|
||||
/// Block receipt if requested.
|
||||
pub receipt: Option<Bytes>,
|
||||
/// Block message queue if requested.
|
||||
pub message_queue: Option<Bytes>,
|
||||
}
|
||||
|
||||
#[serde(untagged)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
/// Identifies starting point of a block sequence.
|
||||
pub enum FromBlock {
|
||||
/// Start with given hash.
|
||||
Hash(HeaderHash),
|
||||
/// Start with given block number.
|
||||
Number(BlockNumber),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
/// Block enumeration direction.
|
||||
pub enum Direction {
|
||||
/// Enumerate in ascending order (from child to parent).
|
||||
Ascending,
|
||||
/// Enumerate in descendfing order (from parent to canonical child).
|
||||
Descending,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
/// A network message.
|
||||
pub enum Message {
|
||||
/// Status packet.
|
||||
Status(Status),
|
||||
/// Block request.
|
||||
BlockRequest(BlockRequest),
|
||||
/// Block response.
|
||||
BlockResponse(BlockResponse),
|
||||
/// Block announce.
|
||||
BlockAnnounce(BlockAnnounce),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Status {
|
||||
/// Protocol version.
|
||||
pub version: u32,
|
||||
/// Supported roles.
|
||||
pub roles: Vec<Role>,
|
||||
/// Best block number.
|
||||
pub best_number: BlockNumber,
|
||||
/// Best block hash.
|
||||
pub best_hash: HeaderHash,
|
||||
/// Genesis block hash.
|
||||
pub genesis_hash: HeaderHash,
|
||||
/// Signatue of `best_hash` made with validator address. Required for the validator role.
|
||||
pub validator_signature: Option<Signature>,
|
||||
/// Validator address. Required for the validator role.
|
||||
pub validator_id: Option<Address>,
|
||||
/// Parachain id. Required for the collator role.
|
||||
pub parachain_id: Option<ParachainId>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
/// Request block data from a peer.
|
||||
pub struct BlockRequest {
|
||||
/// Unique request id.
|
||||
pub id: RequestId,
|
||||
/// Bits of block data to request.
|
||||
pub fields: Vec<BlockAttribute>,
|
||||
/// Start from this block.
|
||||
pub from: FromBlock,
|
||||
/// End at this block. An implementation defined maximum is used when unspecified.
|
||||
pub to: Option<HeaderHash>,
|
||||
/// Sequence direction.
|
||||
pub direction: Direction,
|
||||
/// Maximum number of block to return. An implementation defined maximum is used when unspecified.
|
||||
pub max: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
/// Response to `BlockRequest`
|
||||
pub struct BlockResponse {
|
||||
/// Id of a request this response was made for.
|
||||
pub id: RequestId,
|
||||
/// Block data for the requested sequence.
|
||||
pub blocks: Vec<BlockData>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
/// Announce a new complete relay chain block on the network.
|
||||
pub struct BlockAnnounce {
|
||||
/// New block header.
|
||||
pub header: Header,
|
||||
}
|
||||
@@ -0,0 +1,347 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot 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.
|
||||
|
||||
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.?
|
||||
|
||||
use std::collections::{HashMap, HashSet, BTreeMap};
|
||||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
use parking_lot::RwLock;
|
||||
use serde_json;
|
||||
use std::time;
|
||||
use primitives::block::{HeaderHash, TransactionHash, Number as BlockNumber, Header};
|
||||
use network::{PeerId, NodeId};
|
||||
|
||||
use message::{self, Message};
|
||||
use sync::{ChainSync, Status as SyncStatus};
|
||||
use service::Role;
|
||||
use config::ProtocolConfig;
|
||||
use chain::Client;
|
||||
use io::SyncIo;
|
||||
use error;
|
||||
|
||||
const REQUEST_TIMEOUT_SEC: u64 = 15;
|
||||
const PROTOCOL_VERSION: u32 = 0;
|
||||
|
||||
// Lock must always be taken in order declared here.
|
||||
pub struct Protocol {
|
||||
config: ProtocolConfig,
|
||||
chain: Arc<Client>,
|
||||
genesis_hash: HeaderHash,
|
||||
sync: RwLock<ChainSync>,
|
||||
/// All connected peers
|
||||
peers: RwLock<HashMap<PeerId, Peer>>,
|
||||
/// Connected peers pending Status message.
|
||||
handshaking_peers: RwLock<HashMap<PeerId, time::Instant>>,
|
||||
}
|
||||
|
||||
/// Syncing status and statistics
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct ProtocolStatus {
|
||||
/// Sync status.
|
||||
pub sync: SyncStatus,
|
||||
/// Total number of connected peers
|
||||
pub num_peers: usize,
|
||||
/// Total number of active peers.
|
||||
pub num_active_peers: usize,
|
||||
}
|
||||
|
||||
/// Peer information
|
||||
struct Peer {
|
||||
/// Protocol version
|
||||
protocol_version: u32,
|
||||
/// Roles
|
||||
roles: Role,
|
||||
/// Peer best block hash
|
||||
best_hash: HeaderHash,
|
||||
/// Peer best block number
|
||||
best_number: BlockNumber,
|
||||
/// Pending block request if any
|
||||
block_request: Option<message::BlockRequest>,
|
||||
/// Request timestamp
|
||||
request_timestamp: Option<time::Instant>,
|
||||
/// Holds a set of transactions recently sent to this peer to avoid spamming.
|
||||
_last_sent_transactions: HashSet<TransactionHash>,
|
||||
/// Request counter,
|
||||
request_id: message::RequestId,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PeerInfo {
|
||||
/// Roles
|
||||
pub roles: Role,
|
||||
/// Protocol version
|
||||
pub protocol_version: u32,
|
||||
/// Peer best block hash
|
||||
pub best_hash: HeaderHash,
|
||||
/// Peer best block number
|
||||
pub best_number: BlockNumber,
|
||||
}
|
||||
|
||||
/// Transaction stats
|
||||
#[derive(Debug)]
|
||||
pub struct TransactionStats {
|
||||
/// Block number where this TX was first seen.
|
||||
pub first_seen: u64,
|
||||
/// Peers it was propagated to.
|
||||
pub propagated_to: BTreeMap<NodeId, usize>,
|
||||
}
|
||||
|
||||
impl Protocol {
|
||||
/// Create a new instance.
|
||||
pub fn new(config: ProtocolConfig, chain: Arc<Client>) -> error::Result<Protocol> {
|
||||
let info = chain.info()?;
|
||||
let protocol = Protocol {
|
||||
config: config,
|
||||
chain: chain,
|
||||
genesis_hash: info.chain.genesis_hash,
|
||||
sync: RwLock::new(ChainSync::new(&info)),
|
||||
peers: RwLock::new(HashMap::new()),
|
||||
handshaking_peers: RwLock::new(HashMap::new()),
|
||||
};
|
||||
Ok(protocol)
|
||||
}
|
||||
|
||||
/// Returns protocol status
|
||||
pub fn status(&self) -> ProtocolStatus {
|
||||
let sync = self.sync.read();
|
||||
let peers = self.peers.read();
|
||||
ProtocolStatus {
|
||||
sync: sync.status(),
|
||||
num_peers: peers.values().count(),
|
||||
num_active_peers: peers.values().filter(|p| p.block_request.is_some()).count(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_packet(&self, io: &mut SyncIo, peer_id: PeerId, data: &[u8]) {
|
||||
let message: Message = match serde_json::from_slice(data) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
debug!("Invalid packet from {}: {}", peer_id, e);
|
||||
io.disable_peer(peer_id);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
match message {
|
||||
Message::Status(s) => self.on_status_message(io, peer_id, s),
|
||||
Message::BlockRequest(r) => self.on_block_request(io, peer_id, r),
|
||||
Message::BlockResponse(r) => {
|
||||
let request = {
|
||||
let mut peers = self.peers.write();
|
||||
if let Some(ref mut peer) = peers.get_mut(&peer_id) {
|
||||
peer.request_timestamp = None;
|
||||
match mem::replace(&mut peer.block_request, None) {
|
||||
Some(r) => r,
|
||||
None => {
|
||||
debug!("Unexpected response packet from {}", peer_id);
|
||||
io.disable_peer(peer_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debug!("Unexpected packet from {}", peer_id);
|
||||
io.disable_peer(peer_id);
|
||||
return;
|
||||
}
|
||||
};
|
||||
if request.id != r.id {
|
||||
trace!("Ignoring mismatched response packet from {}", peer_id);
|
||||
return;
|
||||
}
|
||||
self.on_block_response(io, peer_id, request, r);
|
||||
},
|
||||
Message::BlockAnnounce(announce) => {
|
||||
self.on_block_announce(io, peer_id, announce);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_message(&self, io: &mut SyncIo, peer_id: PeerId, mut message: Message) {
|
||||
let mut peers = self.peers.write();
|
||||
if let Some(ref mut peer) = peers.get_mut(&peer_id) {
|
||||
match &mut message {
|
||||
&mut Message::BlockRequest(ref mut r) => {
|
||||
peer.block_request = Some(r.clone());
|
||||
peer.request_timestamp = Some(time::Instant::now());
|
||||
r.id = peer.request_id;
|
||||
peer.request_id = peer.request_id + 1;
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
let data = serde_json::to_vec(&message).expect("Serializer is infallible; qed");
|
||||
if let Err(e) = io.send(peer_id, data) {
|
||||
debug!(target:"sync", "Error sending message: {:?}", e);
|
||||
io.disconnect_peer(peer_id);
|
||||
}
|
||||
}
|
||||
|
||||
/// Called when a new peer is connected
|
||||
pub fn on_peer_connected(&self, io: &mut SyncIo, peer_id: PeerId) {
|
||||
trace!(target: "sync", "Connected {}: {}", peer_id, io.peer_info(peer_id));
|
||||
self.handshaking_peers.write().insert(peer_id, time::Instant::now());
|
||||
self.send_status(io, peer_id);
|
||||
}
|
||||
|
||||
/// Called by peer when it is disconnecting
|
||||
pub fn on_peer_disconnected(&self, io: &mut SyncIo, peer: PeerId) {
|
||||
trace!(target: "sync", "Disconnecting {}: {}", peer, io.peer_info(peer));
|
||||
let removed = {
|
||||
let mut peers = self.peers.write();
|
||||
let mut handshaking_peers = self.handshaking_peers.write();
|
||||
handshaking_peers.remove(&peer);
|
||||
peers.remove(&peer).is_some()
|
||||
};
|
||||
if removed {
|
||||
self.sync.write().peer_disconnected(io, self, peer);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_block_request(&self, _io: &mut SyncIo, _peer_id: PeerId, _request: message::BlockRequest) {
|
||||
}
|
||||
|
||||
pub fn on_block_response(&self, io: &mut SyncIo, peer_id: PeerId, request: message::BlockRequest, response: message::BlockResponse) {
|
||||
// TODO: validate response
|
||||
self.sync.write().on_block_data(io, self, peer_id, request, response);
|
||||
}
|
||||
|
||||
pub fn tick(&self, io: &mut SyncIo) {
|
||||
self.maintain_peers(io);
|
||||
}
|
||||
|
||||
fn maintain_peers(&self, io: &mut SyncIo) {
|
||||
let tick = time::Instant::now();
|
||||
let mut aborting = Vec::new();
|
||||
{
|
||||
let peers = self.peers.read();
|
||||
let handshaking_peers = self.handshaking_peers.read();
|
||||
for (peer_id, timestamp) in peers.iter()
|
||||
.filter_map(|(id, peer)| peer.request_timestamp.as_ref().map(|r| (id, r)))
|
||||
.chain(handshaking_peers.iter()) {
|
||||
if (tick - *timestamp).as_secs() > REQUEST_TIMEOUT_SEC {
|
||||
trace!(target:"sync", "Timeout {}", peer_id);
|
||||
io.disconnect_peer(*peer_id);
|
||||
aborting.push(*peer_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
for p in aborting {
|
||||
self.on_peer_disconnected(io, p);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn peer_info(&self, peer: PeerId) -> Option<PeerInfo> {
|
||||
self.peers.read().get(&peer).map(|p| {
|
||||
PeerInfo {
|
||||
roles: p.roles,
|
||||
protocol_version: p.protocol_version,
|
||||
best_hash: p.best_hash,
|
||||
best_number: p.best_number,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Called by peer to report status
|
||||
fn on_status_message(&self, io: &mut SyncIo, peer_id: PeerId, status: message::Status) {
|
||||
trace!(target: "sync", "New peer {} {:?}", peer_id, status);
|
||||
if io.is_expired() {
|
||||
trace!(target: "sync", "Status packet from expired session {}:{}", peer_id, io.peer_info(peer_id));
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
let mut peers = self.peers.write();
|
||||
let mut handshaking_peers = self.handshaking_peers.write();
|
||||
if peers.contains_key(&peer_id) {
|
||||
debug!(target: "sync", "Unexpected status packet from {}:{}", peer_id, io.peer_info(peer_id));
|
||||
return;
|
||||
}
|
||||
if status.genesis_hash != self.genesis_hash {
|
||||
io.disable_peer(peer_id);
|
||||
trace!(target: "sync", "Peer {} genesis hash mismatch (ours: {}, theirs: {})", peer_id, self.genesis_hash, status.genesis_hash);
|
||||
return;
|
||||
}
|
||||
if status.version != PROTOCOL_VERSION {
|
||||
io.disable_peer(peer_id);
|
||||
trace!(target: "sync", "Peer {} unsupported eth protocol ({})", peer_id, status.version);
|
||||
return;
|
||||
}
|
||||
|
||||
let peer = Peer {
|
||||
protocol_version: status.version,
|
||||
roles: status.roles.into(),
|
||||
best_hash: status.best_hash,
|
||||
best_number: status.best_number,
|
||||
block_request: None,
|
||||
request_timestamp: None,
|
||||
_last_sent_transactions: HashSet::new(),
|
||||
request_id: 0,
|
||||
};
|
||||
peers.insert(peer_id.clone(), peer);
|
||||
handshaking_peers.remove(&peer_id);
|
||||
debug!(target: "sync", "Connected {} {}", peer_id, io.peer_info(peer_id));
|
||||
}
|
||||
self.sync.write().new_peer(io, self, peer_id);
|
||||
}
|
||||
|
||||
/// Send Status message
|
||||
fn send_status(&self, io: &mut SyncIo, peer_id: PeerId) {
|
||||
if let Ok(info) = self.chain.info() {
|
||||
let status = message::Status {
|
||||
version: PROTOCOL_VERSION,
|
||||
genesis_hash: info.chain.genesis_hash,
|
||||
roles: self.config.roles.into(),
|
||||
best_number: info.chain.best_number,
|
||||
best_hash: info.chain.best_hash,
|
||||
validator_signature: None,
|
||||
validator_id: None,
|
||||
parachain_id: None,
|
||||
};
|
||||
self.send_message(io, peer_id, Message::Status(status))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn abort(&self) {
|
||||
let mut sync = self.sync.write();
|
||||
let mut peers = self.peers.write();
|
||||
let mut handshaking_peers = self.handshaking_peers.write();
|
||||
sync.clear();
|
||||
peers.clear();
|
||||
handshaking_peers.clear();
|
||||
}
|
||||
|
||||
pub fn on_block_announce(&self, io: &mut SyncIo, peer_id: PeerId, announce: message::BlockAnnounce) {
|
||||
let header = announce.header;
|
||||
self.sync.write().on_block_announce(io, self, peer_id, &header);
|
||||
}
|
||||
|
||||
pub fn on_block_imported(&self, header: &Header) {
|
||||
self.sync.write().update_chain_info(&header);
|
||||
}
|
||||
|
||||
pub fn on_new_transactions(&self) {
|
||||
}
|
||||
|
||||
pub fn transactions_stats(&self) -> BTreeMap<TransactionHash, TransactionStats> {
|
||||
BTreeMap::new()
|
||||
}
|
||||
|
||||
pub fn chain(&self) -> &Client {
|
||||
&*self.chain
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot 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.
|
||||
|
||||
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.?
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::collections::{BTreeMap};
|
||||
use std::io;
|
||||
use network::{NetworkProtocolHandler, NetworkService, NetworkContext, HostInfo, PeerId, ProtocolId,
|
||||
NetworkConfiguration , NonReservedPeerMode, ErrorKind};
|
||||
use primitives::block::{TransactionHash, Header};
|
||||
use core_io::{TimerToken};
|
||||
use io::NetSyncIo;
|
||||
use protocol::{Protocol, ProtocolStatus, PeerInfo as ProtocolPeerInfo, TransactionStats};
|
||||
use config::{ProtocolConfig};
|
||||
use error::Error;
|
||||
use chain::Client;
|
||||
|
||||
/// Polkadot devp2p protocol id
|
||||
pub const DOT_PROTOCOL_ID: ProtocolId = *b"dot";
|
||||
|
||||
bitflags! {
|
||||
pub struct Role: u32 {
|
||||
const NONE = 0b00000000;
|
||||
const FULL = 0b00000001;
|
||||
const LIGHT = 0b00000010;
|
||||
const VALIDATOR = 0b00000100;
|
||||
const COLLATOR = 0b00001000;
|
||||
}
|
||||
}
|
||||
|
||||
/// Sync status
|
||||
pub trait SyncProvider: Send + Sync {
|
||||
/// Get sync status
|
||||
fn status(&self) -> ProtocolStatus;
|
||||
/// Get peers information
|
||||
fn peers(&self) -> Vec<PeerInfo>;
|
||||
/// Get this node id if available.
|
||||
fn node_id(&self) -> Option<String>;
|
||||
/// Returns propagation count for pending transactions.
|
||||
fn transactions_stats(&self) -> BTreeMap<TransactionHash, TransactionStats>;
|
||||
}
|
||||
|
||||
/// Peer connection information
|
||||
#[derive(Debug)]
|
||||
pub struct PeerInfo {
|
||||
/// Public node id
|
||||
pub id: Option<String>,
|
||||
/// Node client ID
|
||||
pub client_version: String,
|
||||
/// Capabilities
|
||||
pub capabilities: Vec<String>,
|
||||
/// Remote endpoint address
|
||||
pub remote_address: String,
|
||||
/// Local endpoint address
|
||||
pub local_address: String,
|
||||
/// Dot protocol info.
|
||||
pub dot_info: Option<ProtocolPeerInfo>,
|
||||
}
|
||||
|
||||
/// Service initialization parameters.
|
||||
pub struct Params {
|
||||
/// Configuration.
|
||||
pub config: ProtocolConfig,
|
||||
/// Network layer configuration.
|
||||
pub network_config: NetworkConfiguration,
|
||||
/// Polkadot relay chain access point.
|
||||
pub chain: Arc<Client>,
|
||||
}
|
||||
|
||||
/// Polkadot network service. Handles network IO and manages connectivity.
|
||||
pub struct Service {
|
||||
/// Network service
|
||||
network: NetworkService,
|
||||
/// Devp2p protocol handler
|
||||
handler: Arc<ProtocolHandler>,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
/// Creates and register protocol with the network service
|
||||
pub fn new(params: Params) -> Result<Arc<Service>, Error> {
|
||||
|
||||
let service = NetworkService::new(params.network_config.clone(), None)?;
|
||||
|
||||
let sync = Arc::new(Service {
|
||||
network: service,
|
||||
handler: Arc::new(ProtocolHandler {
|
||||
protocol: Protocol::new(params.config, params.chain.clone())?,
|
||||
}),
|
||||
});
|
||||
|
||||
Ok(sync)
|
||||
}
|
||||
|
||||
/// Called when a new block is imported by the client.
|
||||
pub fn on_block_imported(&self, header: &Header) {
|
||||
self.handler.protocol.on_block_imported(header)
|
||||
}
|
||||
|
||||
/// Called when new transactons are imported by the client.
|
||||
pub fn on_new_transactions(&self) {
|
||||
self.handler.protocol.on_new_transactions()
|
||||
}
|
||||
|
||||
fn start(&self) {
|
||||
match self.network.start().map_err(Into::into) {
|
||||
Err(ErrorKind::Io(ref e)) if e.kind() == io::ErrorKind::AddrInUse =>
|
||||
warn!("Network port {:?} is already in use, make sure that another instance of Polkadot client is not running or change the port using the --port option.", self.network.config().listen_address.expect("Listen address is not set.")),
|
||||
Err(err) => warn!("Error starting network: {}", err),
|
||||
_ => {},
|
||||
};
|
||||
self.network.register_protocol(self.handler.clone(), DOT_PROTOCOL_ID, 1, &[0u8])
|
||||
.unwrap_or_else(|e| warn!("Error registering polkadot protocol: {:?}", e));
|
||||
}
|
||||
|
||||
fn stop(&self) {
|
||||
self.handler.protocol.abort();
|
||||
self.network.stop().unwrap_or_else(|e| warn!("Error stopping network: {:?}", e));
|
||||
}
|
||||
}
|
||||
|
||||
impl SyncProvider for Service {
|
||||
/// Get sync status
|
||||
fn status(&self) -> ProtocolStatus {
|
||||
self.handler.protocol.status()
|
||||
}
|
||||
|
||||
/// Get sync peers
|
||||
fn peers(&self) -> Vec<PeerInfo> {
|
||||
self.network.with_context_eval(DOT_PROTOCOL_ID, |ctx| {
|
||||
let peer_ids = self.network.connected_peers();
|
||||
|
||||
peer_ids.into_iter().filter_map(|peer_id| {
|
||||
let session_info = match ctx.session_info(peer_id) {
|
||||
None => return None,
|
||||
Some(info) => info,
|
||||
};
|
||||
|
||||
Some(PeerInfo {
|
||||
id: session_info.id.map(|id| id.hex()),
|
||||
client_version: session_info.client_version,
|
||||
capabilities: session_info.peer_capabilities.into_iter().map(|c| c.to_string()).collect(),
|
||||
remote_address: session_info.remote_address,
|
||||
local_address: session_info.local_address,
|
||||
dot_info: self.handler.protocol.peer_info(peer_id),
|
||||
})
|
||||
}).collect()
|
||||
}).unwrap_or_else(Vec::new)
|
||||
}
|
||||
|
||||
fn node_id(&self) -> Option<String> {
|
||||
self.network.external_url()
|
||||
}
|
||||
|
||||
fn transactions_stats(&self) -> BTreeMap<TransactionHash, TransactionStats> {
|
||||
self.handler.protocol.transactions_stats()
|
||||
}
|
||||
}
|
||||
|
||||
struct ProtocolHandler {
|
||||
/// Protocol handler
|
||||
protocol: Protocol,
|
||||
}
|
||||
|
||||
impl NetworkProtocolHandler for ProtocolHandler {
|
||||
fn initialize(&self, io: &NetworkContext, _host_info: &HostInfo) {
|
||||
io.register_timer(0, 1000).expect("Error registering sync timer");
|
||||
}
|
||||
|
||||
fn read(&self, io: &NetworkContext, peer: &PeerId, _packet_id: u8, data: &[u8]) {
|
||||
self.protocol.handle_packet(&mut NetSyncIo::new(io), *peer, data);
|
||||
}
|
||||
|
||||
fn connected(&self, io: &NetworkContext, peer: &PeerId) {
|
||||
self.protocol.on_peer_connected(&mut NetSyncIo::new(io), *peer);
|
||||
}
|
||||
|
||||
fn disconnected(&self, io: &NetworkContext, peer: &PeerId) {
|
||||
self.protocol.on_peer_disconnected(&mut NetSyncIo::new(io), *peer);
|
||||
}
|
||||
|
||||
fn timeout(&self, io: &NetworkContext, _timer: TimerToken) {
|
||||
self.protocol.tick(&mut NetSyncIo::new(io));
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for managing network
|
||||
pub trait ManageNetwork : Send + Sync {
|
||||
/// Set to allow unreserved peers to connect
|
||||
fn accept_unreserved_peers(&self);
|
||||
/// Set to deny unreserved peers to connect
|
||||
fn deny_unreserved_peers(&self);
|
||||
/// Remove reservation for the peer
|
||||
fn remove_reserved_peer(&self, peer: String) -> Result<(), String>;
|
||||
/// Add reserved peer
|
||||
fn add_reserved_peer(&self, peer: String) -> Result<(), String>;
|
||||
/// Start network
|
||||
fn start_network(&self);
|
||||
/// Stop network
|
||||
fn stop_network(&self);
|
||||
}
|
||||
|
||||
|
||||
impl ManageNetwork for Service {
|
||||
fn accept_unreserved_peers(&self) {
|
||||
self.network.set_non_reserved_mode(NonReservedPeerMode::Accept);
|
||||
}
|
||||
|
||||
fn deny_unreserved_peers(&self) {
|
||||
self.network.set_non_reserved_mode(NonReservedPeerMode::Deny);
|
||||
}
|
||||
|
||||
fn remove_reserved_peer(&self, peer: String) -> Result<(), String> {
|
||||
self.network.remove_reserved_peer(&peer).map_err(|e| format!("{:?}", e))
|
||||
}
|
||||
|
||||
fn add_reserved_peer(&self, peer: String) -> Result<(), String> {
|
||||
self.network.add_reserved_peer(&peer).map_err(|e| format!("{:?}", e))
|
||||
}
|
||||
|
||||
fn start_network(&self) {
|
||||
self.start();
|
||||
}
|
||||
|
||||
fn stop_network(&self) {
|
||||
self.stop();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot 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.
|
||||
|
||||
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.?
|
||||
|
||||
use std::collections::HashMap;
|
||||
use io::SyncIo;
|
||||
use protocol::Protocol;
|
||||
use network::PeerId;
|
||||
use client::{ImportResult, BlockStatus, ClientInfo};
|
||||
use primitives::block::{HeaderHash, Number as BlockNumber, Header};
|
||||
use blocks::{self, BlockCollection};
|
||||
use message::{self, Message};
|
||||
use super::header_hash;
|
||||
|
||||
// Maximum parallel requests for a block.
|
||||
const MAX_BLOCK_DOWNLOAD: usize = 1;
|
||||
|
||||
struct PeerSync {
|
||||
pub common_hash: HeaderHash,
|
||||
pub common_number: BlockNumber,
|
||||
pub best_hash: HeaderHash,
|
||||
pub best_number: BlockNumber,
|
||||
pub state: PeerSyncState,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
pub enum PeerSyncState {
|
||||
AncestorSearch(BlockNumber),
|
||||
Available,
|
||||
DownloadingNew(BlockNumber),
|
||||
DownloadingStale(HeaderHash),
|
||||
}
|
||||
|
||||
/// Relay chain sync strategy.
|
||||
pub struct ChainSync {
|
||||
genesis_hash: HeaderHash,
|
||||
peers: HashMap<PeerId, PeerSync>,
|
||||
blocks: BlockCollection,
|
||||
best_queued_number: BlockNumber,
|
||||
best_queued_hash: HeaderHash,
|
||||
required_block_attributes: Vec<message::BlockAttribute>,
|
||||
}
|
||||
|
||||
/// Syncing status and statistics
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Status;
|
||||
|
||||
impl ChainSync {
|
||||
pub fn new(info: &ClientInfo) -> ChainSync {
|
||||
ChainSync {
|
||||
genesis_hash: info.chain.genesis_hash,
|
||||
peers: HashMap::new(),
|
||||
blocks: BlockCollection::new(),
|
||||
best_queued_hash: info.best_queued_hash.unwrap_or(info.chain.best_hash),
|
||||
best_queued_number: info.best_queued_number.unwrap_or(info.chain.best_number),
|
||||
required_block_attributes: vec![message::BlockAttribute::Header, message::BlockAttribute::Body],
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns sync status
|
||||
pub fn status(&self) -> Status {
|
||||
Status
|
||||
}
|
||||
|
||||
pub fn new_peer(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId) {
|
||||
if let Some(info) = protocol.peer_info(peer_id) {
|
||||
match (protocol.chain().block_status(&info.best_hash), info.best_number) {
|
||||
(Err(e), _) => {
|
||||
debug!(target:"sync", "Error reading blockchain: {:?}", e);
|
||||
io.disconnect_peer(peer_id);
|
||||
},
|
||||
(Ok(BlockStatus::KnownBad), _) => {
|
||||
debug!(target:"sync", "New peer with known bad best block {} ({}).", info.best_hash, info.best_number);
|
||||
io.disable_peer(peer_id);
|
||||
},
|
||||
(Ok(BlockStatus::Unknown), 0) => {
|
||||
debug!(target:"sync", "New peer with unkown genesis hash {} ({}).", info.best_hash, info.best_number);
|
||||
io.disable_peer(peer_id);
|
||||
},
|
||||
(Ok(BlockStatus::Unknown), _) => {
|
||||
debug!(target:"sync", "New peer with unkown best hash {} ({}), searching for common ancestor.", info.best_hash, info.best_number);
|
||||
self.peers.insert(peer_id, PeerSync {
|
||||
common_hash: self.genesis_hash,
|
||||
common_number: 0,
|
||||
best_hash: info.best_hash,
|
||||
best_number: info.best_number,
|
||||
state: PeerSyncState::AncestorSearch(info.best_number - 1),
|
||||
});
|
||||
Self::request_ancestry(io, protocol, peer_id, info.best_number - 1)
|
||||
},
|
||||
(Ok(BlockStatus::Queued), _) | (Ok(BlockStatus::InChain), _) => {
|
||||
debug!(target:"sync", "New peer with known best hash {} ({}).", info.best_hash, info.best_number);
|
||||
self.peers.insert(peer_id, PeerSync {
|
||||
common_hash: info.best_hash,
|
||||
common_number: info.best_number,
|
||||
best_hash: info.best_hash,
|
||||
best_number: info.best_number,
|
||||
state: PeerSyncState::Available,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_block_data(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, _request: message::BlockRequest, response: message::BlockResponse) {
|
||||
let count = response.blocks.len();
|
||||
let mut imported: usize = 0;
|
||||
let new_blocks = if let Some(ref mut peer) = self.peers.get_mut(&peer_id) {
|
||||
match peer.state {
|
||||
PeerSyncState::DownloadingNew(start_block) => {
|
||||
self.blocks.clear_peer_download(peer_id);
|
||||
peer.state = PeerSyncState::Available;
|
||||
|
||||
self.blocks.insert(start_block, response.blocks, peer_id);
|
||||
self.blocks.drain(self.best_queued_number + 1)
|
||||
},
|
||||
PeerSyncState::DownloadingStale(_) => {
|
||||
peer.state = PeerSyncState::Available;
|
||||
response.blocks.into_iter().map(|b| blocks::BlockData {
|
||||
origin: peer_id,
|
||||
block: b
|
||||
}).collect()
|
||||
},
|
||||
PeerSyncState::AncestorSearch(n) => {
|
||||
match response.blocks.get(0) {
|
||||
Some(ref block) => {
|
||||
match protocol.chain().block_hash(n) {
|
||||
Ok(Some(block_hash)) if block_hash == block.hash => {
|
||||
peer.common_hash = block.hash;
|
||||
peer.common_number = n;
|
||||
peer.state = PeerSyncState::Available;
|
||||
trace!(target:"sync", "Found common ancestor for peer {}: {} ({})", peer_id, block.hash, n);
|
||||
vec![]
|
||||
},
|
||||
Ok(_) if n > 0 => {
|
||||
let n = n - 1;
|
||||
peer.state = PeerSyncState::AncestorSearch(n);
|
||||
Self::request_ancestry(io, protocol, peer_id, n);
|
||||
return;
|
||||
},
|
||||
Ok(_) => { // genesis mismatch
|
||||
io.disable_peer(peer_id);
|
||||
return;
|
||||
},
|
||||
Err(e) => {
|
||||
debug!(target:"sync", "Error reading blockchain: {:?}", e);
|
||||
io.disconnect_peer(peer_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
trace!(target:"sync", "Invalid response when searching for ancestor from {}", peer_id);
|
||||
io.disconnect_peer(peer_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
PeerSyncState::Available => Vec::new(),
|
||||
}
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
// Blocks in the response/drain should be in ascending order.
|
||||
for block in new_blocks {
|
||||
let origin = block.origin;
|
||||
let block = block.block;
|
||||
if let Some(header) = block.header {
|
||||
let number = header.number;
|
||||
let hash = header_hash(&header);
|
||||
let parent = header.parent_hash;
|
||||
let result = protocol.chain().import(header, block.body);
|
||||
match result {
|
||||
Ok(ImportResult::AlreadyInChain) => {
|
||||
trace!(target: "sync", "Block already in chain {}: {:?}", number, hash);
|
||||
self.block_imported(&hash, number);
|
||||
},
|
||||
Ok(ImportResult::AlreadyQueued) => {
|
||||
trace!(target: "sync", "Block already queued {}: {:?}", number, hash);
|
||||
self.block_imported(&hash, number);
|
||||
},
|
||||
Ok(ImportResult::Queued) => {
|
||||
trace!(target: "sync", "Block queued {}: {:?}", number, hash);
|
||||
self.block_imported(&hash, number);
|
||||
imported = imported + 1;
|
||||
},
|
||||
Ok(ImportResult::UnknownParent) => {
|
||||
debug!(target: "sync", "Block with unknown parent {}: {:?}, parent: {:?}", number, hash, parent);
|
||||
self.restart(io, protocol);
|
||||
return;
|
||||
},
|
||||
Ok(ImportResult::KnownBad) => {
|
||||
debug!(target: "sync", "Bad block {}: {:?}", number, hash);
|
||||
io.disable_peer(origin); //TODO: use persistent ID
|
||||
self.restart(io, protocol);
|
||||
return;
|
||||
}
|
||||
Err(e) => {
|
||||
debug!(target: "sync", "Error importing block {}: {:?}: {:?}", number, hash, e);
|
||||
self.restart(io, protocol);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
trace!(target: "sync", "Imported {} of {}", imported, count);
|
||||
self.maintain_sync(io, protocol);
|
||||
}
|
||||
|
||||
fn maintain_sync(&mut self, io: &mut SyncIo, protocol: &Protocol) {
|
||||
let peers: Vec<PeerId> = self.peers.keys().map(|p| *p).collect();
|
||||
for peer in peers {
|
||||
self.download_new(io, protocol, peer);
|
||||
}
|
||||
}
|
||||
|
||||
fn block_imported(&mut self, hash: &HeaderHash, number: BlockNumber) {
|
||||
if number > self.best_queued_number {
|
||||
self.best_queued_number = number;
|
||||
self.best_queued_hash = *hash;
|
||||
}
|
||||
// Update common blocks
|
||||
for (_, peer) in self.peers.iter_mut() {
|
||||
if peer.best_number >= number {
|
||||
peer.common_number = number;
|
||||
peer.common_hash = *hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_chain_info(&mut self, best_header: &Header ) {
|
||||
let hash = header_hash(&best_header);
|
||||
self.block_imported(&hash, best_header.number)
|
||||
}
|
||||
|
||||
pub fn on_block_announce(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, header: &Header) {
|
||||
let hash = header_hash(&header);
|
||||
if let Some(ref mut peer) = self.peers.get_mut(&peer_id) {
|
||||
if header.number > peer.best_number {
|
||||
peer.best_number = header.number;
|
||||
peer.best_hash = hash;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if !self.is_known_or_already_downloading(protocol, &hash) {
|
||||
let stale = header.number <= self.best_queued_number;
|
||||
if stale {
|
||||
if !self.is_known_or_already_downloading(protocol, &header.parent_hash) {
|
||||
trace!(target: "sync", "Ignoring unkown stale block announce from {}: {} {:?}", peer_id, hash, header);
|
||||
} else {
|
||||
trace!(target: "sync", "Downloading new stale block announced from {}: {} {:?}", peer_id, hash, header);
|
||||
self.download_stale(io, protocol, peer_id, &hash);
|
||||
}
|
||||
} else {
|
||||
trace!(target: "sync", "Downloading new block announced from {}: {} {:?}", peer_id, hash, header);
|
||||
self.download_new(io, protocol, peer_id);
|
||||
}
|
||||
} else {
|
||||
trace!(target: "sync", "Known block announce from {}: {}", peer_id, hash);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_known_or_already_downloading(&self, protocol: &Protocol, hash: &HeaderHash) -> bool {
|
||||
self.peers.iter().any(|(_, p)| p.state == PeerSyncState::DownloadingStale(*hash))
|
||||
|| protocol.chain().block_status(hash).ok().map_or(false, |s| s != BlockStatus::Unknown)
|
||||
}
|
||||
|
||||
pub fn peer_disconnected(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId) {
|
||||
self.blocks.clear_peer_download(peer_id);
|
||||
self.peers.remove(&peer_id);
|
||||
self.maintain_sync(io, protocol);
|
||||
}
|
||||
|
||||
pub fn restart(&mut self, io: &mut SyncIo, protocol: &Protocol) {
|
||||
self.blocks.clear();
|
||||
let ids: Vec<PeerId> = self.peers.keys().map(|p| *p).collect();
|
||||
for id in ids {
|
||||
self.new_peer(io, protocol, id);
|
||||
}
|
||||
match protocol.chain().info() {
|
||||
Ok(info) => {
|
||||
self.best_queued_hash = info.best_queued_hash.unwrap_or(info.chain.best_hash);
|
||||
self.best_queued_number = info.best_queued_number.unwrap_or(info.chain.best_number);
|
||||
},
|
||||
Err(e) => {
|
||||
debug!(target:"sync", "Error reading blockchain: {:?}", e);
|
||||
self.best_queued_hash = self.genesis_hash;
|
||||
self.best_queued_number = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.blocks.clear();
|
||||
self.peers.clear();
|
||||
}
|
||||
|
||||
// Download old block.
|
||||
fn download_stale(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, hash: &HeaderHash) {
|
||||
if let Some(ref mut peer) = self.peers.get_mut(&peer_id) {
|
||||
match peer.state {
|
||||
PeerSyncState::Available => {
|
||||
let request = message::BlockRequest {
|
||||
id: 0,
|
||||
fields: self.required_block_attributes.clone(),
|
||||
from: message::FromBlock::Hash(*hash),
|
||||
to: None,
|
||||
direction: message::Direction::Ascending,
|
||||
max: Some(1),
|
||||
};
|
||||
peer.state = PeerSyncState::DownloadingStale(*hash);
|
||||
protocol.send_message(io, peer_id, Message::BlockRequest(request));
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Issue a request for a peer to download new blocks, if any are available
|
||||
fn download_new(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId) {
|
||||
if let Some(ref mut peer) = self.peers.get_mut(&peer_id) {
|
||||
match peer.state {
|
||||
PeerSyncState::Available => {
|
||||
if let Some(range) = self.blocks.needed_blocks(peer_id, MAX_BLOCK_DOWNLOAD, peer.common_number, peer.best_number) {
|
||||
let request = message::BlockRequest {
|
||||
id: 0,
|
||||
fields: self.required_block_attributes.clone(),
|
||||
from: message::FromBlock::Number(range.start),
|
||||
to: None,
|
||||
direction: message::Direction::Ascending,
|
||||
max: Some((range.end - range.start) as u32),
|
||||
};
|
||||
peer.state = PeerSyncState::DownloadingNew(range.start);
|
||||
protocol.send_message(io, peer_id, Message::BlockRequest(request));
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn request_ancestry(io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, block: BlockNumber) {
|
||||
let request = message::BlockRequest {
|
||||
id: 0,
|
||||
fields: vec![message::BlockAttribute::Header],
|
||||
from: message::FromBlock::Number(block),
|
||||
to: None,
|
||||
direction: message::Direction::Ascending,
|
||||
max: Some(1),
|
||||
};
|
||||
protocol.send_message(io, peer_id, Message::BlockRequest(request));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -20,24 +20,30 @@ use bytes;
|
||||
use hash::H256;
|
||||
use parachain;
|
||||
|
||||
/// Used to refer to a block number.
|
||||
pub type Number = u64;
|
||||
|
||||
/// Hash used to refer to a block hash.
|
||||
pub type HeaderHash = H256;
|
||||
|
||||
/// Hash used to refer to a transaction hash.
|
||||
pub type TransactionHash = H256;
|
||||
|
||||
/// Execution log (event)
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct Log(#[serde(with="bytes")] pub Vec<u8>);
|
||||
|
||||
/// A relay chain block header.
|
||||
///
|
||||
/// https://github.com/w3f/polkadot-spec/blob/master/spec.md#header
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Header {
|
||||
/// Block parent's hash.
|
||||
pub parent_hash: HeaderHash,
|
||||
/// Block number.
|
||||
pub number: u64,
|
||||
pub number: Number,
|
||||
/// State root after this transition.
|
||||
pub state_root: H256,
|
||||
/// Parachain activity bitfield
|
||||
@@ -50,7 +56,7 @@ pub struct Header {
|
||||
///
|
||||
/// Included candidates should be sorted by parachain ID, and without duplicate
|
||||
/// IDs.
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Body {
|
||||
|
||||
@@ -98,7 +98,7 @@ pub struct HeadData(#[serde(with="bytes")] pub Vec<u8>);
|
||||
pub struct ValidationCode(#[serde(with="bytes")] pub Vec<u8>);
|
||||
|
||||
/// Activitiy bit field
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct Activity(#[serde(with="bytes")] pub Vec<u8>);
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
use primitives::block;
|
||||
use client;
|
||||
use state_machine;
|
||||
|
||||
mod error;
|
||||
|
||||
@@ -35,11 +36,12 @@ build_rpc_trait! {
|
||||
}
|
||||
}
|
||||
|
||||
impl<B> ChainApi for B where
|
||||
B: client::Blockchain + Send + Sync + 'static,
|
||||
B::Error: ::std::error::Error + Send,
|
||||
impl<B, E> ChainApi for client::Client<B, E> where
|
||||
B: client::backend::Backend + Send + Sync + 'static,
|
||||
E: state_machine::CodeExecutor + Send + Sync + 'static,
|
||||
client::error::Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>,
|
||||
{
|
||||
fn header(&self, hash: block::HeaderHash) -> Result<Option<block::Header>> {
|
||||
self.header(&hash).chain_err(|| "Blockchain error")
|
||||
client::Client::header(self, &hash).chain_err(|| "Blockchain error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,28 +14,27 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use primitives::parachain;
|
||||
use polkadot_executor as executor;
|
||||
use client;
|
||||
use super::*;
|
||||
|
||||
use test_helpers::Blockchain;
|
||||
|
||||
#[test]
|
||||
fn should_return_header() {
|
||||
let state = Blockchain::default();
|
||||
let client = client::new_in_mem(executor::executor()).unwrap();
|
||||
|
||||
assert_matches!(
|
||||
ChainApi::header(&state, 0.into()),
|
||||
ChainApi::header(&client, "11265ce45dd2baaaf071f6df8c5a44f0ed1d85a50e71451ff2d4345e57d12e3a".into()),
|
||||
Ok(Some(ref x)) if x == &block::Header {
|
||||
parent_hash: 0.into(),
|
||||
number: 0,
|
||||
state_root: 0.into(),
|
||||
parachain_activity: parachain::Activity(vec![0]),
|
||||
parachain_activity: Default::default(),
|
||||
logs: vec![],
|
||||
}
|
||||
);
|
||||
|
||||
assert_matches!(
|
||||
ChainApi::header(&state, 5.into()),
|
||||
ChainApi::header(&client, 5.into()),
|
||||
Ok(None)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,3 @@ extern crate assert_matches;
|
||||
|
||||
pub mod chain;
|
||||
pub mod state;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_helpers;
|
||||
|
||||
@@ -42,8 +42,9 @@ build_rpc_trait! {
|
||||
}
|
||||
|
||||
impl<B, E> StateApi for Client<B, E> where
|
||||
B: client::Blockchain + Send + Sync + 'static,
|
||||
B: client::backend::Backend + Send + Sync + 'static,
|
||||
E: state_machine::CodeExecutor + Send + Sync + 'static,
|
||||
client::error::Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>,
|
||||
{
|
||||
fn storage(&self, key: StorageKey, block: block::HeaderHash) -> Result<StorageData> {
|
||||
Ok(self.storage(&block, &key)?)
|
||||
|
||||
@@ -18,14 +18,15 @@ use super::*;
|
||||
use polkadot_executor as executor;
|
||||
|
||||
use self::error::{Error, ErrorKind};
|
||||
use test_helpers::Blockchain;
|
||||
use client;
|
||||
|
||||
#[test]
|
||||
fn should_return_storage() {
|
||||
let client = Client::new(Blockchain::default(), executor::executor());
|
||||
let client = client::new_in_mem(executor::executor()).unwrap();
|
||||
let genesis_hash = "11265ce45dd2baaaf071f6df8c5a44f0ed1d85a50e71451ff2d4345e57d12e3a".into();
|
||||
|
||||
assert_matches!(
|
||||
StateApi::storage(&client, StorageKey(vec![10]), 0.into()),
|
||||
StateApi::storage(&client, StorageKey(vec![10]), genesis_hash),
|
||||
Ok(ref x) if x.0.is_empty()
|
||||
)
|
||||
}
|
||||
@@ -34,10 +35,11 @@ fn should_return_storage() {
|
||||
#[ignore] // TODO: [ToDr] reenable once we can properly mock the wasm executor env
|
||||
fn should_call_contract() {
|
||||
// TODO [ToDr] Fix test after we are able to mock state.
|
||||
let client = Client::new(Blockchain::default(), executor::executor());
|
||||
let client = client::new_in_mem(executor::executor()).unwrap();
|
||||
let genesis_hash = "11265ce45dd2baaaf071f6df8c5a44f0ed1d85a50e71451ff2d4345e57d12e3a".into();
|
||||
|
||||
assert_matches!(
|
||||
StateApi::call(&client, "balanceOf".into(), CallData(vec![1,2,3]), 0.into()),
|
||||
StateApi::call(&client, "balanceOf".into(), CallData(vec![1,2,3]), genesis_hash),
|
||||
Err(Error(ErrorKind::Client(client::error::ErrorKind::Execution(_)), _))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ impl error::Error for Void {
|
||||
|
||||
/// In-memory backend. Fully recomputes tries on each commit but useful for
|
||||
/// tests.
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Clone)]
|
||||
pub struct InMemory {
|
||||
inner: MemoryState, // keeps all the state in memory.
|
||||
}
|
||||
@@ -82,7 +82,7 @@ impl InMemory {
|
||||
impl Backend for InMemory {
|
||||
type Error = Void;
|
||||
|
||||
fn storage(&self, key: &[u8]) -> Result<&[u8], Void> {
|
||||
fn storage(&self, key: &[u8]) -> Result<&[u8], Self::Error> {
|
||||
Ok(self.inner.storage(key).unwrap_or(&[]))
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ pub enum Update {
|
||||
}
|
||||
|
||||
// in-memory section of the state.
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Clone)]
|
||||
struct MemoryState {
|
||||
storage: HashMap<Vec<u8>, Vec<u8>>,
|
||||
}
|
||||
@@ -160,7 +160,7 @@ pub trait Externalities {
|
||||
}
|
||||
|
||||
/// Code execution engine.
|
||||
pub trait CodeExecutor: Sized {
|
||||
pub trait CodeExecutor: Sized + Send + Sync {
|
||||
/// Externalities error type.
|
||||
type Error: Error;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user