Merge branch 'master' into rh-grandpa-dynamic2

This commit is contained in:
Robert Habermeier
2018-10-27 18:12:33 +02:00
123 changed files with 4972 additions and 4239 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ stages:
- test - test
- build - build
image: parity/rust:substrate image: parity/rust:nightly
variables: variables:
CI_SERVER_NAME: "GitLab CI" CI_SERVER_NAME: "GitLab CI"
+175 -170
View File
@@ -5,7 +5,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"aes-soft 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "aes-soft 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"aesni 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "aesni 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ctr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ctr 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@@ -329,8 +329,8 @@ dependencies = [
"isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
"simplelog 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "simplelog 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@@ -427,7 +427,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "ctr" name = "ctr"
version = "0.1.0" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -451,7 +451,7 @@ dependencies = [
"base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"chashmap 2.2.1 (git+https://github.com/redox-os/tfs)", "chashmap 2.2.1 (git+https://github.com/redox-os/tfs)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
"tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@@ -704,7 +704,7 @@ dependencies = [
[[package]] [[package]]
name = "h2" name = "h2"
version = "0.1.12" version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -805,13 +805,13 @@ dependencies = [
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "0.12.11" version = "0.12.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"h2 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "h2 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
"httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -894,21 +894,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "jsonrpc-core" name = "jsonrpc-core"
version = "9.0.0" version = "9.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git#8d41129955e9abf08399cd052b4a6df4e0743ad6" source = "git+https://github.com/paritytech/jsonrpc.git#207a277b098943864ecaf22dbab7a5e309866d6b"
dependencies = [ dependencies = [
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "jsonrpc-http-server" name = "jsonrpc-http-server"
version = "9.0.0" version = "9.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git#8d41129955e9abf08399cd052b4a6df4e0743ad6" source = "git+https://github.com/paritytech/jsonrpc.git#207a277b098943864ecaf22dbab7a5e309866d6b"
dependencies = [ dependencies = [
"hyper 0.12.11 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)",
"jsonrpc-server-utils 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", "jsonrpc-server-utils 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -919,17 +919,17 @@ dependencies = [
[[package]] [[package]]
name = "jsonrpc-macros" name = "jsonrpc-macros"
version = "9.0.0" version = "9.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git#8d41129955e9abf08399cd052b4a6df4e0743ad6" source = "git+https://github.com/paritytech/jsonrpc.git#207a277b098943864ecaf22dbab7a5e309866d6b"
dependencies = [ dependencies = [
"jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)",
"jsonrpc-pubsub 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", "jsonrpc-pubsub 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "jsonrpc-pubsub" name = "jsonrpc-pubsub"
version = "9.0.0" version = "9.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git#8d41129955e9abf08399cd052b4a6df4e0743ad6" source = "git+https://github.com/paritytech/jsonrpc.git#207a277b098943864ecaf22dbab7a5e309866d6b"
dependencies = [ dependencies = [
"jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -939,7 +939,7 @@ dependencies = [
[[package]] [[package]]
name = "jsonrpc-server-utils" name = "jsonrpc-server-utils"
version = "9.0.0" version = "9.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git#8d41129955e9abf08399cd052b4a6df4e0743ad6" source = "git+https://github.com/paritytech/jsonrpc.git#207a277b098943864ecaf22dbab7a5e309866d6b"
dependencies = [ dependencies = [
"bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -955,7 +955,7 @@ dependencies = [
[[package]] [[package]]
name = "jsonrpc-ws-server" name = "jsonrpc-ws-server"
version = "9.0.0" version = "9.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git#8d41129955e9abf08399cd052b4a6df4e0743ad6" source = "git+https://github.com/paritytech/jsonrpc.git#207a277b098943864ecaf22dbab7a5e309866d6b"
dependencies = [ dependencies = [
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)",
@@ -1216,8 +1216,8 @@ dependencies = [
"libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)", "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
"multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)", "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
"owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@@ -1276,7 +1276,7 @@ dependencies = [
"aes-ctr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "aes-ctr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"asn1_der 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "asn1_der 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"ctr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ctr 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)", "eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)", "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
@@ -1514,7 +1514,7 @@ dependencies = [
"bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"multihash 0.8.1-pre (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)", "multihash 0.8.1-pre (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"unsigned-varint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unsigned-varint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@@ -1598,37 +1598,20 @@ dependencies = [
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"node-executor 0.1.0", "node-executor 0.1.0",
"node-network 0.1.0",
"node-primitives 0.1.0",
"node-runtime 0.1.0",
"sr-primitives 0.1.0",
"substrate-cli 0.3.0",
"substrate-network 0.1.0",
"substrate-primitives 0.1.0",
"substrate-service 0.3.0",
"substrate-service-test 0.3.0",
"substrate-transaction-pool 0.1.0",
"tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "node-consensus"
version = "0.1.0"
dependencies = [
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"node-primitives 0.1.0", "node-primitives 0.1.0",
"node-runtime 0.1.0", "node-runtime 0.1.0",
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"rhododendron 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"srml-system 0.1.0", "substrate-cli 0.3.0",
"substrate-client 0.1.0", "substrate-client 0.1.0",
"substrate-keyring 0.1.0", "substrate-consensus-aura 0.1.0",
"substrate-network 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-service 0.3.0",
"substrate-service-test 0.3.0",
"substrate-transaction-pool 0.1.0", "substrate-transaction-pool 0.1.0",
"tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@@ -1661,21 +1644,6 @@ dependencies = [
"wabt 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "node-network"
version = "0.1.0"
dependencies = [
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"node-consensus 0.1.0",
"node-primitives 0.1.0",
"rhododendron 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-consensus-rhd 0.1.0",
"substrate-network 0.1.0",
"substrate-primitives 0.1.0",
"tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "node-primitives" name = "node-primitives"
version = "0.1.0" version = "0.1.0"
@@ -1683,8 +1651,8 @@ dependencies = [
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pretty_assertions 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-std 0.1.0", "sr-std 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
@@ -1701,8 +1669,8 @@ dependencies = [
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-api 0.1.0", "sr-api 0.1.0",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
@@ -1720,6 +1688,7 @@ dependencies = [
"srml-system 0.1.0", "srml-system 0.1.0",
"srml-timestamp 0.1.0", "srml-timestamp 0.1.0",
"srml-treasury 0.1.0", "srml-treasury 0.1.0",
"srml-upgrade-key 0.1.0",
"substrate-keyring 0.1.0", "substrate-keyring 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
] ]
@@ -1794,12 +1763,12 @@ dependencies = [
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.37 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "openssl" name = "openssl"
version = "0.10.13" version = "0.10.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1807,12 +1776,12 @@ dependencies = [
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.37 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "openssl-sys" name = "openssl-sys"
version = "0.9.37" version = "0.9.39"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1834,21 +1803,13 @@ name = "parity-bytes"
version = "0.1.0" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "parity-codec"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "parity-codec" name = "parity-codec"
version = "2.1.5" version = "2.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@@ -2201,20 +2162,10 @@ dependencies = [
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "rhododendron"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "rhododendron" name = "rhododendron"
version = "0.4.0" version = "0.4.0"
source = "git+https://github.com/paritytech/rhododendron.git#64b46b577479a3b6c493fa6db5420a265a445ff9" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2357,20 +2308,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.79" version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.79" version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.9 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.12 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@@ -2380,7 +2328,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@@ -2468,7 +2416,7 @@ version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
"slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@@ -2529,8 +2477,8 @@ dependencies = [
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-std 0.1.0", "sr-std 0.1.0",
@@ -2563,8 +2511,8 @@ version = "0.1.0"
dependencies = [ dependencies = [
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-std 0.1.0", "sr-std 0.1.0",
] ]
@@ -2576,8 +2524,8 @@ dependencies = [
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-std 0.1.0", "sr-std 0.1.0",
@@ -2594,8 +2542,8 @@ dependencies = [
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-std 0.1.0", "sr-std 0.1.0",
@@ -2612,8 +2560,8 @@ dependencies = [
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-std 0.1.0", "sr-std 0.1.0",
@@ -2631,8 +2579,8 @@ dependencies = [
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)",
"pwasm-utils 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "pwasm-utils 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-sandbox 0.1.0", "sr-sandbox 0.1.0",
@@ -2652,8 +2600,8 @@ dependencies = [
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-std 0.1.0", "sr-std 0.1.0",
@@ -2672,8 +2620,8 @@ dependencies = [
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-std 0.1.0", "sr-std 0.1.0",
@@ -2690,8 +2638,8 @@ dependencies = [
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-std 0.1.0", "sr-std 0.1.0",
@@ -2708,8 +2656,8 @@ dependencies = [
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-std 0.1.0", "sr-std 0.1.0",
@@ -2727,8 +2675,8 @@ dependencies = [
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-std 0.1.0", "sr-std 0.1.0",
@@ -2747,8 +2695,8 @@ dependencies = [
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-std 0.1.0", "sr-std 0.1.0",
@@ -2771,8 +2719,8 @@ dependencies = [
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-std 0.1.0", "sr-std 0.1.0",
@@ -2787,8 +2735,8 @@ dependencies = [
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-std 0.1.0", "sr-std 0.1.0",
@@ -2803,8 +2751,8 @@ dependencies = [
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-std 0.1.0", "sr-std 0.1.0",
@@ -2821,8 +2769,8 @@ dependencies = [
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-std 0.1.0", "sr-std 0.1.0",
@@ -2832,6 +2780,24 @@ dependencies = [
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
] ]
[[package]]
name = "srml-upgrade-key"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0",
"sr-primitives 0.1.0",
"sr-std 0.1.0",
"srml-consensus 0.1.0",
"srml-support 0.1.0",
"srml-system 0.1.0",
"substrate-primitives 0.1.0",
]
[[package]] [[package]]
name = "stable_deref_trait" name = "stable_deref_trait"
version = "1.1.1" version = "1.1.1"
@@ -2877,7 +2843,7 @@ dependencies = [
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"node-cli 0.1.0", "node-cli 0.1.0",
"vergen 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "vergen 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@@ -2929,7 +2895,7 @@ dependencies = [
"slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-api 0.1.0", "sr-api 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"substrate-consensus-rhd 0.1.0", "substrate-consensus-common 0.1.0",
"substrate-executor 0.1.0", "substrate-executor 0.1.0",
"substrate-keyring 0.1.0", "substrate-keyring 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
@@ -2962,12 +2928,44 @@ dependencies = [
"substrate-trie 0.4.0", "substrate-trie 0.4.0",
] ]
[[package]]
name = "substrate-consensus-aura"
version = "0.1.0"
dependencies = [
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0",
"sr-primitives 0.1.0",
"sr-version 0.1.0",
"srml-consensus 0.1.0",
"srml-support 0.1.0",
"substrate-client 0.1.0",
"substrate-consensus-common 0.1.0",
"substrate-executor 0.1.0",
"substrate-keyring 0.1.0",
"substrate-network 0.1.0",
"substrate-primitives 0.1.0",
"substrate-service 0.3.0",
"substrate-test-client 0.1.0",
"tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "substrate-consensus-common" name = "substrate-consensus-common"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-version 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@@ -2975,21 +2973,25 @@ name = "substrate-consensus-rhd"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"rhododendron 0.4.0 (git+https://github.com/paritytech/rhododendron.git)", "rhododendron 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-version 0.1.0", "sr-version 0.1.0",
"srml-consensus 0.1.0", "srml-consensus 0.1.0",
"srml-support 0.1.0", "srml-support 0.1.0",
"srml-system 0.1.0",
"substrate-client 0.1.0",
"substrate-consensus-common 0.1.0",
"substrate-executor 0.1.0", "substrate-executor 0.1.0",
"substrate-keyring 0.1.0", "substrate-keyring 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-transaction-pool 0.1.0",
"tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@@ -3005,8 +3007,8 @@ dependencies = [
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-version 0.1.0", "sr-version 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
@@ -3053,8 +3055,8 @@ dependencies = [
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-crypto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-crypto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3067,8 +3069,8 @@ version = "0.1.0"
dependencies = [ dependencies = [
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@@ -3088,6 +3090,7 @@ dependencies = [
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"substrate-client 0.1.0", "substrate-client 0.1.0",
"substrate-consensus-common 0.1.0",
"substrate-keyring 0.1.0", "substrate-keyring 0.1.0",
"substrate-network-libp2p 0.1.0", "substrate-network-libp2p 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
@@ -3110,8 +3113,8 @@ dependencies = [
"parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3137,8 +3140,8 @@ dependencies = [
"pretty_assertions 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-std 0.1.0", "sr-std 0.1.0",
"substrate-serializer 0.1.0", "substrate-serializer 0.1.0",
"twox-hash 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "twox-hash 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3164,6 +3167,7 @@ dependencies = [
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"sr-version 0.1.0", "sr-version 0.1.0",
"substrate-client 0.1.0", "substrate-client 0.1.0",
"substrate-consensus-common 0.1.0",
"substrate-executor 0.1.0", "substrate-executor 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-test-client 0.1.0", "substrate-test-client 0.1.0",
@@ -3179,7 +3183,7 @@ dependencies = [
"jsonrpc-pubsub 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", "jsonrpc-pubsub 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)",
"jsonrpc-ws-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", "jsonrpc-ws-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"substrate-rpc 0.1.0", "substrate-rpc 0.1.0",
] ]
@@ -3188,7 +3192,7 @@ dependencies = [
name = "substrate-serializer" name = "substrate-serializer"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@@ -3203,14 +3207,15 @@ dependencies = [
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
"slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"substrate-client 0.1.0", "substrate-client 0.1.0",
"substrate-client-db 0.1.0", "substrate-client-db 0.1.0",
"substrate-consensus-common 0.1.0",
"substrate-executor 0.1.0", "substrate-executor 0.1.0",
"substrate-keystore 0.1.0", "substrate-keystore 0.1.0",
"substrate-network 0.1.0", "substrate-network 0.1.0",
@@ -3233,6 +3238,7 @@ dependencies = [
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"substrate-client 0.1.0", "substrate-client 0.1.0",
"substrate-consensus-common 0.1.0",
"substrate-network 0.1.0", "substrate-network 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-service 0.3.0", "substrate-service 0.3.0",
@@ -3289,6 +3295,7 @@ dependencies = [
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"substrate-client 0.1.0", "substrate-client 0.1.0",
"substrate-consensus-common 0.1.0",
"substrate-executor 0.1.0", "substrate-executor 0.1.0",
"substrate-keyring 0.1.0", "substrate-keyring 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
@@ -3303,8 +3310,8 @@ dependencies = [
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-api 0.1.0", "sr-api 0.1.0",
"sr-io 0.1.0", "sr-io 0.1.0",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
@@ -3324,8 +3331,8 @@ dependencies = [
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-primitives 0.1.0", "sr-primitives 0.1.0",
"substrate-test-runtime 0.1.0", "substrate-test-runtime 0.1.0",
] ]
@@ -3391,7 +3398,7 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "0.15.9" version = "0.15.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3916,7 +3923,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "vergen" name = "vergen"
version = "2.1.2" version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3940,8 +3947,8 @@ name = "wabt"
version = "0.4.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
"wabt-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "wabt-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@@ -4070,7 +4077,7 @@ dependencies = [
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4163,7 +4170,7 @@ dependencies = [
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
"checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015"
"checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda"
"checksum ctr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50ac3add446ec1f8fe3dc007cd838f5b22bbf33186394feac505451ecc43c018" "checksum ctr 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4b669fcb8e20124db86dbd9b01e74ec0e9e420e65381311ce5249864fc7ff0c0"
"checksum ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "630391922b1b893692c6334369ff528dcc3a9d8061ccf4c803aa8f83cb13db5e" "checksum ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "630391922b1b893692c6334369ff528dcc3a9d8061ccf4c803aa8f83cb13db5e"
"checksum datastore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)" = "<none>" "checksum datastore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)" = "<none>"
"checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" "checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8"
@@ -4197,7 +4204,7 @@ dependencies = [
"checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797" "checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797"
"checksum getset 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "54c7f36a235738bb25904d6a2b3dbb28f6f5736cd3918c4bf80d6bb236200782" "checksum getset 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "54c7f36a235738bb25904d6a2b3dbb28f6f5736cd3918c4bf80d6bb236200782"
"checksum globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4743617a7464bbda3c8aec8558ff2f9429047e025771037df561d383337ff865" "checksum globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4743617a7464bbda3c8aec8558ff2f9429047e025771037df561d383337ff865"
"checksum h2 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "a27e7ed946e8335bdf9a191bc1b9b14a03ba822d013d2f58437f4fabcbd7fc2c" "checksum h2 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "7dd33bafe2e6370e6c8eb0cf1b8c5f93390b90acde7e9b03723f166b28b648ed"
"checksum hash-db 0.9.0 (git+https://github.com/paritytech/trie)" = "<none>" "checksum hash-db 0.9.0 (git+https://github.com/paritytech/trie)" = "<none>"
"checksum hash256-std-hasher 0.9.0 (git+https://github.com/paritytech/trie)" = "<none>" "checksum hash256-std-hasher 0.9.0 (git+https://github.com/paritytech/trie)" = "<none>"
"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" "checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461"
@@ -4208,7 +4215,7 @@ dependencies = [
"checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83"
"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e"
"checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2" "checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2"
"checksum hyper 0.12.11 (registry+https://github.com/rust-lang/crates.io-index)" = "78d50abbd1790e0f4c74cb1d4a2211b439bac661d54107ad5564c55e77906762" "checksum hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)" = "4aca412c241a2dd53af261efc7adf7736fdebd67dc0d1cc1ffdbcb9407e0e810"
"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
"checksum indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08173ba1e906efb6538785a8844dd496f5d34f0a2d88038e95195172fc667220" "checksum indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08173ba1e906efb6538785a8844dd496f5d34f0a2d88038e95195172fc667220"
"checksum integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)" = "<none>" "checksum integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)" = "<none>"
@@ -4286,12 +4293,11 @@ dependencies = [
"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
"checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c"
"checksum opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d620c9c26834b34f039489ac0dfdb12c7ac15ccaf818350a64c9b5334a452ad7" "checksum opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d620c9c26834b34f039489ac0dfdb12c7ac15ccaf818350a64c9b5334a452ad7"
"checksum openssl 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "5af9e83eb3c51ee806387d26a43056f3246d865844caa6dd704d2ba7e831c264" "checksum openssl 0.10.14 (registry+https://github.com/rust-lang/crates.io-index)" = "6285ab297861546af7a2753593b3160bfc09f0ab9d1f5bb009e39d81a169b499"
"checksum openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "a3605c298474a3aa69de92d21139fb5e2a81688d308262359d85cdd0d12a7985" "checksum openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "a3605c298474a3aa69de92d21139fb5e2a81688d308262359d85cdd0d12a7985"
"checksum openssl-sys 0.9.37 (registry+https://github.com/rust-lang/crates.io-index)" = "d4edbc8dfa63f557aee3a498179af2cc6a989e12ba1751840046c79afc9e615a" "checksum openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)" = "278c1ad40a89aa1e741a1eed089a2f60b18fab8089c3139b542140fc7d674106"
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
"checksum parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5168b4cf41f3835e4bc6ffb32f51bc9365dc50cb351904595b3931d917fd0c" "checksum parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5168b4cf41f3835e4bc6ffb32f51bc9365dc50cb351904595b3931d917fd0c"
"checksum parity-codec 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bee4edfcfa19892f7178cb299a659866015dc131459865a1d808269cf7e7eb9e"
"checksum parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dca389ea5e1632c89b2ce54f7e2b4a8a8c9d278042222a91e0bf95451218cb4c" "checksum parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dca389ea5e1632c89b2ce54f7e2b4a8a8c9d278042222a91e0bf95451218cb4c"
"checksum parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffa42c2cb493b60b12c75b26e8c94cb734af4df4d7f2cc229dc04c1953dac189" "checksum parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffa42c2cb493b60b12c75b26e8c94cb734af4df4d7f2cc229dc04c1953dac189"
"checksum parity-crypto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c1117f6574377d21309bfa1f7d69ff734120685d92b02c3f362b122585758840" "checksum parity-crypto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c1117f6574377d21309bfa1f7d69ff734120685d92b02c3f362b122585758840"
@@ -4334,8 +4340,7 @@ dependencies = [
"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7"
"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" "checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d"
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
"checksum rhododendron 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e20523445e693f394c0e487113ae656071311c9ee4c1e914441bece8c929b21d" "checksum rhododendron 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a09bc21b21795c366c8bf0e87afb71175f5f736b3a5b279b6f4e81839d0a877b"
"checksum rhododendron 0.4.0 (git+https://github.com/paritytech/rhododendron.git)" = "<none>"
"checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c" "checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c"
"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
@@ -4354,8 +4359,8 @@ dependencies = [
"checksum security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "5421621e836278a0b139268f36eee0dc7e389b784dc3f79d8f11aabadf41bead" "checksum security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "5421621e836278a0b139268f36eee0dc7e389b784dc3f79d8f11aabadf41bead"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "84257ccd054dc351472528c8587b4de2dbf0dc0fe2e634030c1a90bfdacebaa9" "checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef"
"checksum serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "31569d901045afbff7a9479f793177fe9259819aff10ab4f89ef69bbc5f567fe" "checksum serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "225de307c6302bec3898c51ca302fc94a7a1697ef0845fcee6448f33c032249c"
"checksum serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "43344e7ce05d0d8280c5940cabb4964bea626aa58b1ec0e8c73fa2a8512a38ce" "checksum serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "43344e7ce05d0d8280c5940cabb4964bea626aa58b1ec0e8c73fa2a8512a38ce"
"checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c"
"checksum sha1 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "171698ce4ec7cbb93babeb3190021b4d72e96ccb98e33d277ae4ea959d6f2d9e" "checksum sha1 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "171698ce4ec7cbb93babeb3190021b4d72e96ccb98e33d277ae4ea959d6f2d9e"
@@ -4380,7 +4385,7 @@ dependencies = [
"checksum subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc7f6353c2ee5407358d063a14cccc1630804527090a6fb5a9489ce4924280fb" "checksum subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc7f6353c2ee5407358d063a14cccc1630804527090a6fb5a9489ce4924280fb"
"checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" "checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b"
"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
"checksum syn 0.15.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b10ee269228fb723234fce98e9aac0eaed2bd5f1ad2f6930e8d5b93f04445a1a" "checksum syn 0.15.12 (registry+https://github.com/rust-lang/crates.io-index)" = "34ab9797e47d24cb76b8dc4d24ff36807018c7cc549c4cba050b068be0c586b0"
"checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7" "checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7"
"checksum sysinfo 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "11c5f6e8a7a7146f26ffed9a5ff8bab2706f1ac8a413a415e1d211b819d5c24d" "checksum sysinfo 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "11c5f6e8a7a7146f26ffed9a5ff8bab2706f1ac8a413a415e1d211b819d5c24d"
"checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60"
@@ -4437,7 +4442,7 @@ dependencies = [
"checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" "checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4"
"checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum vergen 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4cae5a72131fdf47d4fbc9286393ec8622ec7a5502fbe77b291d9aba21d3f179" "checksum vergen 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "93fb2d57fbc535fcd45548c99b141d2d960995daaf04b864c4d9fe1ea011c819"
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum wabt 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "182ae543249ccf2705f324d233891c1176fca142e137b55ba43d9dbfe93f18a2" "checksum wabt 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "182ae543249ccf2705f324d233891c1176fca142e137b55ba43d9dbfe93f18a2"
+2 -2
View File
@@ -23,6 +23,7 @@ members = [
"core/client", "core/client",
"core/client/db", "core/client/db",
"core/consensus/common", "core/consensus/common",
"core/consensus/aura",
"core/consensus/rhd", "core/consensus/rhd",
"core/executor", "core/executor",
"core/finality-grandpa", "core/finality-grandpa",
@@ -54,6 +55,7 @@ members = [
"srml/system", "srml/system",
"srml/timestamp", "srml/timestamp",
"srml/treasury", "srml/treasury",
"srml/upgrade-key",
"core/serializer", "core/serializer",
"core/service", "core/service",
"core/service/test", "core/service/test",
@@ -64,9 +66,7 @@ members = [
"core/trie", "core/trie",
"core/keystore", "core/keystore",
"node/cli", "node/cli",
"node/consensus",
"node/executor", "node/executor",
"node/network",
"node/primitives", "node/primitives",
"node/runtime", "node/runtime",
"subkey", "subkey",
+106 -5
View File
@@ -221,11 +221,112 @@ cargo run
include::doc/packages/packages.adoc[] include::doc/packages/packages.adoc[]
include::CONTRIBUTING.adoc[leveloffset=+1] == Documentation
include::CODE_OF_CONDUCT.adoc[leveloffset=+1] === Viewing documentation for Substrate packages
You can generate documentation for a Substrate Rust package and have it automatically open in your web browser using https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html#using-rustdoc-with-cargo[rustdoc with Cargo],
(of the The Rustdoc Book), by running the the following command:
```
cargo doc --package <spec> --open
```
Replacing `<spec>` with one of the following (i.e. `cargo doc --package node-cli --open`):
* Substrate Core
[source, shell]
substrate, substrate-bft, substrate-cli, substrate-client, substrate-client-db,
substrate-executor, substrate-finality-grandpa, substrate-keyring, substrate-keystore,
substrate-metadata, substrate-misbehavior-check, substrate-network,
substrate-network-libp2p, substrate-primitives, substrate-rpc, substrate-rpc-servers,
substrate-serializer, substrate-service, substrate-service-test, substrate-state-db,
substrate-state-machine, substrate-telemetry, substrate-test-client,
substrate-test-runtime, substrate-transaction-graph, substrate-transaction-pool,
substrate-trie
* Substrate Runtime
[source, shell]
sr-api, sr-io, sr-primitives, sr-sandbox, sr-std, sr-version
* Substrate Runtime Module Library (SRML)
[source, shell]
srml-balances, srml-consensus, srml-contract, srml-council, srml-democracy, srml-example,
srml-executive, srml-session, srml-staking, srml-support, srml-system, srml-timestamp,
srml-treasury
* Node
[source, shell]
node-cli, node-consensus, node-executor, node-network, node-primitives, node-runtime, node-service
* Subkey
[source, shell]
subkey
=== Contributing to documentation for Substrate packages
https://doc.rust-lang.org/1.9.0/book/documentation.html[Document source code] for Substrate packages by annotating the source code with documentation comments.
Example (generic):
```markdown
/// Summary
///
/// Description
///
/// # Panics
///
/// # Errors
///
/// # Safety
///
/// # Examples
///
/// Summary of Example 1
///
/// ```rust
/// // insert example 1 code here
/// ```
///
```
* Important notes:
** Documentation comments must use annotations with a triple slash `///`
** Modules are documented using `//!`
```
//! Summary (of module)
//!
//! Description (of module)
```
* Special section header is indicated with a hash `#`.
** `Panics` section requires an explanation if the function triggers a panic
** `Errors` section is for describing conditions under which a function of method returns `Err(E)` if it returns a `Result<T, E>`
** `Safety` section requires an explanation if the function is `unsafe`
** `Examples` section includes examples of using the function or method
* Code block annotations for examples are included between triple graves, as shown above.
Instead of including the programming language to use for syntax highlighting as the annotation
after the triple graves, alternative annotations include the `ignore`, `text`, `should_panic`, or `no_run`.
* Summary sentence is a short high level sinngle sentence of its functionality
* Description paragraph is for details additional to the summary sentence
* Missing documentation annotations may be used to identify where to generate warnings with `#![warn(missing_docs)]`
or errors `#![deny(missing_docs)]`
* Hide documentation for items with `#[doc(hidden)]`
=== Contributing to documentation (tests, extended examples, macros) for Substrate packages
The code block annotations in the `# Example` section may be used as https://doc.rust-lang.org/1.9.0/book/documentation.html#documentation-as-tests[documentation as tests and for extended examples].
* Important notes:
** Rustdoc will automatically add a `main()` wrapper around the code block to test it
** https://doc.rust-lang.org/1.9.0/book/documentation.html#documenting-macros[Documentating macros].
** Documentation as tests examples are included when running `cargo test`
== Contributing
=== Contributing Guidelines
include::CONTRIBUTING.adoc[]
=== Contributor Code of Conduct
include::CODE_OF_CONDUCT.adoc[]
== License == License
----
include::LICENSE[] https://github.com/paritytech/substrate/blob/master/LICENSE[LICENSE]
----
+1 -1
View File
@@ -12,7 +12,7 @@ hex-literal = "0.1"
futures = "0.1.17" futures = "0.1.17"
slog = "^2" slog = "^2"
heapsize = "0.4" heapsize = "0.4"
substrate-consensus-rhd = { path = "../consensus/rhd" } substrate-consensus-common = { path = "../consensus/common" }
parity-codec = "2.1" parity-codec = "2.1"
substrate-executor = { path = "../executor" } substrate-executor = { path = "../executor" }
substrate-primitives = { path = "../primitives" } substrate-primitives = { path = "../primitives" }
@@ -1,5 +1,5 @@
= transaction-pool = Client DB
.Summary .Summary
[source, toml] [source, toml]
+25 -12
View File
@@ -534,7 +534,9 @@ impl<Block: BlockT> Backend<Block> {
meta.finalized_hash, f_hash), meta.finalized_hash, f_hash),
).into()) ).into())
} }
transaction.put(columns::META, meta_keys::FINALIZED_BLOCK, f_hash.as_ref());
let lookup_key = ::utils::number_to_lookup_key(f_num);
transaction.put(columns::META, meta_keys::FINALIZED_BLOCK, &lookup_key);
let commit = self.storage.state_db.canonicalize_block(&f_hash); let commit = self.storage.state_db.canonicalize_block(&f_hash);
apply_state_commit(transaction, commit); apply_state_commit(transaction, commit);
@@ -586,11 +588,20 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
-> Result<(), client::error::Error> -> Result<(), client::error::Error>
{ {
let mut transaction = DBTransaction::new(); let mut transaction = DBTransaction::new();
if let Some(pending_block) = operation.pending_block { if let Some(pending_block) = operation.pending_block {
let hash = pending_block.header.hash(); let hash = pending_block.header.hash();
let parent_hash = *pending_block.header.parent_hash(); let parent_hash = *pending_block.header.parent_hash();
let number = pending_block.header.number().clone(); let number = pending_block.header.number().clone();
// blocks in longest chain are keyed by number
let lookup_key = if pending_block.leaf_state.is_best() {
::utils::number_to_lookup_key(number).to_vec()
} else {
// other blocks are keyed by number + hash
::utils::number_and_hash_to_lookup_key(number, hash)
};
if pending_block.leaf_state.is_best() { if pending_block.leaf_state.is_best() {
let meta = self.blockchain.meta.read(); let meta = self.blockchain.meta.read();
@@ -678,17 +689,9 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
} }
} }
transaction.put(columns::META, meta_keys::BEST_BLOCK, hash.as_ref()); transaction.put(columns::META, meta_keys::BEST_BLOCK, &lookup_key);
} }
// blocks in longest chain are keyed by number
let lookup_key = if pending_block.leaf_state.is_best() {
::utils::number_to_lookup_key(number).to_vec()
} else {
// other blocks are keyed by number + hash
::utils::number_and_hash_to_lookup_key(number, hash)
};
transaction.put(columns::HEADER, &lookup_key, &pending_block.header.encode()); transaction.put(columns::HEADER, &lookup_key, &pending_block.header.encode());
if let Some(body) = pending_block.body { if let Some(body) = pending_block.body {
transaction.put(columns::BODY, &lookup_key, &body.encode()); transaction.put(columns::BODY, &lookup_key, &body.encode());
@@ -700,7 +703,7 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
transaction.put(columns::HASH_LOOKUP, hash.as_ref(), &lookup_key); transaction.put(columns::HASH_LOOKUP, hash.as_ref(), &lookup_key);
if number == Zero::zero() { if number == Zero::zero() {
transaction.put(columns::META, meta_keys::FINALIZED_BLOCK, hash.as_ref()); transaction.put(columns::META, meta_keys::FINALIZED_BLOCK, &lookup_key);
transaction.put(columns::META, meta_keys::GENESIS_HASH, hash.as_ref()); transaction.put(columns::META, meta_keys::GENESIS_HASH, hash.as_ref());
} }
@@ -797,7 +800,8 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
|| client::error::ErrorKind::UnknownBlock( || client::error::ErrorKind::UnknownBlock(
format!("Error reverting to {}. Block header not found.", best)))?; format!("Error reverting to {}. Block header not found.", best)))?;
transaction.put(columns::META, meta_keys::BEST_BLOCK, header.hash().as_ref()); let lookup_key = ::utils::number_to_lookup_key(header.number().clone());
transaction.put(columns::META, meta_keys::BEST_BLOCK, &lookup_key);
transaction.delete(columns::HASH_LOOKUP, header.hash().as_ref()); transaction.delete(columns::HASH_LOOKUP, header.hash().as_ref());
self.storage.db.write(transaction).map_err(db_err)?; self.storage.db.write(transaction).map_err(db_err)?;
self.blockchain.update_meta(header.hash().clone(), best.clone(), true, false); self.blockchain.update_meta(header.hash().clone(), best.clone(), true, false);
@@ -927,6 +931,7 @@ mod tests {
#[test] #[test]
fn block_hash_inserted_correctly() { fn block_hash_inserted_correctly() {
let backing = {
let db = Backend::<Block>::new_test(1, 0); let db = Backend::<Block>::new_test(1, 0);
for i in 0..10 { for i in 0..10 {
assert!(db.blockchain().hash(i).unwrap().is_none()); assert!(db.blockchain().hash(i).unwrap().is_none());
@@ -962,6 +967,14 @@ mod tests {
assert!(db.blockchain().hash(i).unwrap().is_some()) assert!(db.blockchain().hash(i).unwrap().is_some())
} }
db.storage.db.clone()
};
let backend = Backend::<Block>::from_kvdb(backing, PruningMode::keep_blocks(1), 0).unwrap();
assert_eq!(backend.blockchain().info().unwrap().best_number, 9);
for i in 0..10 {
assert!(backend.blockchain().hash(i).unwrap().is_some())
}
} }
#[test] #[test]
+11 -10
View File
@@ -196,7 +196,8 @@ impl<Block: BlockT> LightStorage<Block> {
).into()) ).into())
} }
transaction.put(columns::META, meta_keys::FINALIZED_BLOCK, hash.as_ref()); let lookup_key = ::utils::number_to_lookup_key(header.number().clone());
transaction.put(columns::META, meta_keys::FINALIZED_BLOCK, &lookup_key);
// build new CHT if required // build new CHT if required
if let Some(new_cht_number) = cht::is_build_required(cht::SIZE, *header.number()) { if let Some(new_cht_number) = cht::is_build_required(cht::SIZE, *header.number()) {
@@ -244,6 +245,14 @@ impl<Block> LightBlockchainStorage<Block> for LightStorage<Block>
let number = *header.number(); let number = *header.number();
let parent_hash = *header.parent_hash(); let parent_hash = *header.parent_hash();
// blocks in longest chain are keyed by number
let lookup_key = if leaf_state.is_best() {
::utils::number_to_lookup_key(number).to_vec()
} else {
// other blocks are keyed by number + hash
::utils::number_and_hash_to_lookup_key(number, hash)
};
if leaf_state.is_best() { if leaf_state.is_best() {
// handle reorg. // handle reorg.
{ {
@@ -298,17 +307,9 @@ impl<Block> LightBlockchainStorage<Block> for LightStorage<Block>
} }
} }
transaction.put(columns::META, meta_keys::BEST_BLOCK, hash.as_ref()); transaction.put(columns::META, meta_keys::BEST_BLOCK, &lookup_key);
} }
// blocks in longest chain are keyed by number
let lookup_key = if leaf_state.is_best() {
::utils::number_to_lookup_key(number).to_vec()
} else {
// other blocks are keyed by number + hash
::utils::number_and_hash_to_lookup_key(number, hash)
};
transaction.put(columns::HEADER, &lookup_key, &header.encode()); transaction.put(columns::HEADER, &lookup_key, &header.encode());
transaction.put(columns::HASH_LOOKUP, hash.as_ref(), &lookup_key); transaction.put(columns::HASH_LOOKUP, hash.as_ref(), &lookup_key);
+1
View File
@@ -53,6 +53,7 @@ pub mod meta_keys {
} }
/// Database metadata. /// Database metadata.
#[derive(Debug)]
pub struct Meta<N, H> { pub struct Meta<N, H> {
/// Hash of the best known block. /// Hash of the best known block.
pub best_hash: H, pub best_hash: H,
+1 -1
View File
@@ -150,7 +150,7 @@ where
let heap_pages = state.storage(well_known_keys::HEAP_PAGES) let heap_pages = state.storage(well_known_keys::HEAP_PAGES)
.map_err(|e| error::ErrorKind::Execution(Box::new(e)))? .map_err(|e| error::ErrorKind::Execution(Box::new(e)))?
.and_then(|v| u64::decode(&mut &v[..])) .and_then(|v| u64::decode(&mut &v[..]))
.unwrap_or(8) as usize; .unwrap_or(1024) as usize;
let mut ext = Ext::new(&mut overlay, &state, self.backend.changes_trie_storage()); let mut ext = Ext::new(&mut overlay, &state, self.backend.changes_trie_storage());
self.executor.runtime_version(&mut ext, heap_pages, &code) self.executor.runtime_version(&mut ext, heap_pages, &code)
+127 -186
View File
@@ -26,6 +26,7 @@ use runtime_primitives::{
generic::{BlockId, SignedBlock, Block as RuntimeBlock}, generic::{BlockId, SignedBlock, Block as RuntimeBlock},
transaction_validity::{TransactionValidity, TransactionTag}, transaction_validity::{TransactionValidity, TransactionTag},
}; };
use consensus::{ImportBlock, ImportResult, BlockOrigin};
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, As, NumberFor, CurrentHeight, BlockNumberToHash}; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, As, NumberFor, CurrentHeight, BlockNumberToHash};
use runtime_primitives::{ApplyResult, BuildStorage}; use runtime_primitives::{ApplyResult, BuildStorage};
use runtime_api as api; use runtime_api as api;
@@ -44,7 +45,7 @@ use blockchain::{self, Info as ChainInfo, Backend as ChainBackend, HeaderBackend
use call_executor::{CallExecutor, LocalCallExecutor}; use call_executor::{CallExecutor, LocalCallExecutor};
use executor::{RuntimeVersion, RuntimeInfo}; use executor::{RuntimeVersion, RuntimeInfo};
use notifications::{StorageNotifications, StorageEventStream}; use notifications::{StorageNotifications, StorageEventStream};
use {cht, error, in_mem, block_builder, genesis}; use {cht, error, in_mem, block_builder, genesis, consensus};
/// Type that implements `futures::Stream` of block import events. /// Type that implements `futures::Stream` of block import events.
pub type ImportNotifications<Block> = mpsc::UnboundedReceiver<BlockImportNotification<Block>>; pub type ImportNotifications<Block> = mpsc::UnboundedReceiver<BlockImportNotification<Block>>;
@@ -106,21 +107,6 @@ pub struct ClientInfo<Block: BlockT> {
pub best_queued_hash: Option<Block::Hash>, pub best_queued_hash: Option<Block::Hash>,
} }
/// Block import result.
#[derive(Debug)]
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,
}
/// Block status. /// Block status.
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum BlockStatus { pub enum BlockStatus {
@@ -134,70 +120,6 @@ pub enum BlockStatus {
Unknown, Unknown,
} }
/// Block data origin.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum BlockOrigin {
/// Genesis block built into the client.
Genesis,
/// Block is part of the initial sync with the network.
NetworkInitialSync,
/// Block was broadcasted on the network.
NetworkBroadcast,
/// Block that was received from the network and validated in the consensus process.
ConsensusBroadcast,
/// Block that was collated by this node.
Own,
/// Block was imported from a file.
File,
}
/// Data required to import a Block
pub struct ImportBlock<Block: BlockT> {
/// Origin of the Block
pub origin: BlockOrigin,
/// Header
pub header: Block::Header,
/// Justification provided for this block from the outside
pub external_justification: Justification,
/// Internal Justification for the block
pub internal_justification: Vec<u8>, // Block::Digest::DigestItem?
/// Block's body
pub body: Option<Vec<Block::Extrinsic>>,
/// Is this block finalized already?
/// `true` implies instant finality.
pub finalized: bool,
/// Auxiliary consensus data produced by the block.
/// Contains a list of key-value pairs. If values are `None`, the keys
/// will be deleted.
pub auxiliary: Vec<(Vec<u8>, Option<Vec<u8>>)>,
}
impl<Block: BlockT> ImportBlock<Block> {
/// Deconstruct the justified header into parts.
pub fn into_inner(self)
-> (
BlockOrigin,
<Block as BlockT>::Header,
Justification,
Justification,
Option<Vec<<Block as BlockT>::Extrinsic>>,
bool,
Vec<(Vec<u8>, Option<Vec<u8>>)>,
) {
(
self.origin,
self.header,
self.external_justification,
self.internal_justification,
self.body,
self.finalized,
self.auxiliary,
)
}
}
/// Summary of an imported block /// Summary of an imported block
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct BlockImportNotification<Block: BlockT> { pub struct BlockImportNotification<Block: BlockT> {
@@ -222,6 +144,41 @@ pub struct FinalityNotification<Block: BlockT> {
pub header: Block::Header, pub header: Block::Header,
} }
// used in importing a block, where additional changes are made after the runtime
// executed.
enum PrePostHeader<H> {
// they are the same: no post-runtime digest items.
Same(H),
// different headers (pre, post).
Different(H, H),
}
impl<H> PrePostHeader<H> {
// get a reference to the "pre-header" -- the header as it should be just after the runtime.
fn pre(&self) -> &H {
match *self {
PrePostHeader::Same(ref h) => h,
PrePostHeader::Different(ref h, _) => h,
}
}
// get a reference to the "post-header" -- the header as it should be after all changes are applied.
fn post(&self) -> &H {
match *self {
PrePostHeader::Same(ref h) => h,
PrePostHeader::Different(_, ref h) => h,
}
}
// convert to the "post-header" -- the header as it should be after all changes are applied.
fn into_post(self) -> H {
match self {
PrePostHeader::Same(h) => h,
PrePostHeader::Different(_, h) => h,
}
}
}
/// Create an instance of in-memory client. /// Create an instance of in-memory client.
pub fn new_in_mem<E, Block, S>( pub fn new_in_mem<E, Block, S>(
executor: E, executor: E,
@@ -346,11 +303,6 @@ impl<B, E, Block> Client<B, E, Block> where
&self.executor &self.executor
} }
/// Returns the runtime metadata.
pub fn metadata(&self, id: &BlockId<Block>) -> error::Result<Vec<u8>> {
self.executor.call(id, "metadata",&[]).map(|v| v.return_data)
}
/// Reads storage value at a given block + key, returning read proof. /// Reads storage value at a given block + key, returning read proof.
pub fn read_proof(&self, id: &BlockId<Block>, key: &[u8]) -> error::Result<Vec<Vec<u8>>> { pub fn read_proof(&self, id: &BlockId<Block>, key: &[u8]) -> error::Result<Vec<Vec<u8>>> {
self.state_at(id) self.state_at(id)
@@ -518,52 +470,6 @@ impl<B, E, Block> Client<B, E, Block> where
) )
} }
/// Import a checked and validated block
pub fn import_block(
&self,
import_block: ImportBlock<Block>,
new_authorities: Option<Vec<AuthorityId>>,
) -> error::Result<ImportResult> {
let (
origin,
header,
_,
justification,
body,
finalized,
_aux, // TODO: write this to DB also
) = import_block.into_inner();
let parent_hash = header.parent_hash().clone();
match self.backend.blockchain().status(BlockId::Hash(parent_hash))? {
blockchain::BlockStatus::InChain => {},
blockchain::BlockStatus::Unknown => return Ok(ImportResult::UnknownParent),
}
let hash = header.hash();
let _import_lock = self.import_lock.lock();
let height: u64 = header.number().as_();
*self.importing_block.write() = Some(hash);
let result = self.execute_and_import_block(
origin,
hash,
header,
justification,
body,
new_authorities,
finalized,
);
*self.importing_block.write() = None;
telemetry!("block.import";
"height" => height,
"best" => ?hash,
"origin" => ?origin
);
result
}
// TODO [ToDr] Optimize and re-use tags from the pool. // TODO [ToDr] Optimize and re-use tags from the pool.
fn transaction_tags(&self, at: Block::Hash, body: &Option<Vec<Block::Extrinsic>>) -> error::Result<Vec<TransactionTag>> { fn transaction_tags(&self, at: Block::Hash, body: &Option<Vec<Block::Extrinsic>>) -> error::Result<Vec<TransactionTag>> {
let id = BlockId::Hash(at); let id = BlockId::Hash(at);
@@ -592,13 +498,13 @@ impl<B, E, Block> Client<B, E, Block> where
&self, &self,
origin: BlockOrigin, origin: BlockOrigin,
hash: Block::Hash, hash: Block::Hash,
header: Block::Header, import_headers: PrePostHeader<Block::Header>,
justification: Justification, justification: Justification,
body: Option<Vec<Block::Extrinsic>>, body: Option<Vec<Block::Extrinsic>>,
authorities: Option<Vec<AuthorityId>>, authorities: Option<Vec<AuthorityId>>,
finalized: bool, finalized: bool,
) -> error::Result<ImportResult> { ) -> error::Result<ImportResult> {
let parent_hash = header.parent_hash().clone(); let parent_hash = import_headers.post().parent_hash().clone();
match self.backend.blockchain().status(BlockId::Hash(hash))? { match self.backend.blockchain().status(BlockId::Hash(hash))? {
blockchain::BlockStatus::InChain => return Ok(ImportResult::AlreadyInChain), blockchain::BlockStatus::InChain => return Ok(ImportResult::AlreadyInChain),
blockchain::BlockStatus::Unknown => {}, blockchain::BlockStatus::Unknown => {},
@@ -632,12 +538,13 @@ impl<B, E, Block> Client<B, E, Block> where
transaction_state, transaction_state,
&mut overlay, &mut overlay,
"execute_block", "execute_block",
&<Block as BlockT>::new(header.clone(), body.clone().unwrap_or_default()).encode(), &<Block as BlockT>::new(import_headers.pre().clone(), body.clone().unwrap_or_default()).encode(),
match (origin, self.block_execution_strategy) { match (origin, self.block_execution_strategy) {
(BlockOrigin::NetworkInitialSync, _) | (_, ExecutionStrategy::NativeWhenPossible) => (BlockOrigin::NetworkInitialSync, _) | (_, ExecutionStrategy::NativeWhenPossible) =>
ExecutionManager::NativeWhenPossible, ExecutionManager::NativeWhenPossible,
(_, ExecutionStrategy::AlwaysWasm) => ExecutionManager::AlwaysWasm, (_, ExecutionStrategy::AlwaysWasm) => ExecutionManager::AlwaysWasm,
_ => ExecutionManager::Both(|wasm_result, native_result| { _ => ExecutionManager::Both(|wasm_result, native_result| {
let header = import_headers.post();
warn!("Consensus error between wasm and native block execution at block {}", hash); warn!("Consensus error between wasm and native block execution at block {}", hash);
warn!(" Header {:?}", header); warn!(" Header {:?}", header);
warn!(" Native result {:?}", native_result); warn!(" Native result {:?}", native_result);
@@ -659,7 +566,7 @@ impl<B, E, Block> Client<B, E, Block> where
}; };
// TODO: non longest-chain rule. // TODO: non longest-chain rule.
let is_new_best = finalized || header.number() > &last_best_number; let is_new_best = finalized || import_headers.post().number() > &last_best_number;
let leaf_state = if finalized { let leaf_state = if finalized {
::backend::NewBlockState::Final ::backend::NewBlockState::Final
} else if is_new_best { } else if is_new_best {
@@ -668,10 +575,10 @@ impl<B, E, Block> Client<B, E, Block> where
::backend::NewBlockState::Normal ::backend::NewBlockState::Normal
}; };
trace!("Imported {}, (#{}), best={}, origin={:?}", hash, header.number(), is_new_best, origin); trace!("Imported {}, (#{}), best={}, origin={:?}", hash, import_headers.post().number(), is_new_best, origin);
transaction.set_block_data( transaction.set_block_data(
header.clone(), import_headers.post().clone(),
body, body,
Some(justification), Some(justification),
leaf_state, leaf_state,
@@ -698,7 +605,7 @@ impl<B, E, Block> Client<B, E, Block> where
if finalized { if finalized {
let notification = FinalityNotification::<Block> { let notification = FinalityNotification::<Block> {
hash, hash,
header: header.clone(), header: import_headers.post().clone(),
}; };
self.finality_notification_sinks.lock() self.finality_notification_sinks.lock()
@@ -708,7 +615,7 @@ impl<B, E, Block> Client<B, E, Block> where
let notification = BlockImportNotification::<Block> { let notification = BlockImportNotification::<Block> {
hash, hash,
origin, origin,
header, header: import_headers.into_post(),
is_new_best, is_new_best,
tags, tags,
}; };
@@ -986,6 +893,84 @@ impl<B, E, Block> Client<B, E, Block> where
} }
} }
impl<B, E, Block> consensus::BlockImport<Block> for Client<B, E, Block> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Clone,
Block: BlockT,
{
type Error = Error;
/// Import a checked and validated block
fn import_block(
&self,
import_block: ImportBlock<Block>,
new_authorities: Option<Vec<AuthorityId>>,
) -> Result<ImportResult, Self::Error> {
use runtime_primitives::traits::Digest;
let ImportBlock {
origin,
header,
external_justification,
post_runtime_digests,
body,
finalized,
..
} = import_block;
let parent_hash = header.parent_hash().clone();
match self.backend.blockchain().status(BlockId::Hash(parent_hash))? {
blockchain::BlockStatus::InChain => {},
blockchain::BlockStatus::Unknown => return Ok(ImportResult::UnknownParent),
}
let import_headers = if post_runtime_digests.is_empty() {
PrePostHeader::Same(header)
} else {
let mut post_header = header.clone();
for item in post_runtime_digests {
post_header.digest_mut().push(item);
}
PrePostHeader::Different(header, post_header)
};
let hash = import_headers.post().hash();
let _import_lock = self.import_lock.lock();
let height: u64 = import_headers.post().number().as_();
*self.importing_block.write() = Some(hash);
let result = self.execute_and_import_block(
origin,
hash,
import_headers,
external_justification,
body,
new_authorities,
finalized,
);
*self.importing_block.write() = None;
telemetry!("block.import";
"height" => height,
"best" => ?hash,
"origin" => ?origin
);
result.map_err(|e| e.into())
}
}
impl<B, E, Block> consensus::Authorities<Block> for Client<B, E, Block> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Clone,
Block: BlockT,
{
type Error = Error;
fn authorities(&self, at: &BlockId<Block>) -> Result<Vec<AuthorityId>, Self::Error> {
self.authorities_at(at).map_err(|e| e.into())
}
}
impl<B, E, Block> CurrentHeight for Client<B, E, Block> where impl<B, E, Block> CurrentHeight for Client<B, E, Block> where
B: backend::Backend<Block, Blake2Hasher>, B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Clone, E: CallExecutor<Block, Blake2Hasher> + Clone,
@@ -1076,7 +1061,7 @@ impl<B, E, Block> api::Core<Block, AuthorityId> for Client<B, E, Block> where
} }
} }
impl<B, E, Block> api::Metadata<Block> for Client<B, E, Block> where impl<B, E, Block> api::Metadata<Block, Vec<u8>> for Client<B, E, Block> where
B: backend::Backend<Block, Blake2Hasher>, B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>, E: CallExecutor<Block, Blake2Hasher>,
Block: BlockT, Block: BlockT,
@@ -1084,7 +1069,7 @@ impl<B, E, Block> api::Metadata<Block> for Client<B, E, Block> where
type Error = Error; type Error = Error;
fn metadata(&self, at: &BlockId<Block>) -> Result<Vec<u8>, Self::Error> { fn metadata(&self, at: &BlockId<Block>) -> Result<Vec<u8>, Self::Error> {
self.call_api_at(at, "metadata", &()) self.executor.call(at, "metadata",&[]).map(|v| v.return_data)
} }
} }
@@ -1142,26 +1127,6 @@ impl<B, E, Block> api::BlockBuilder<Block> for Client<B, E, Block> where
} }
} }
impl<B, E, Block> api::OldTxQueue<Block> for Client<B, E, Block> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>,
Block: BlockT,
{
type Error = Error;
fn account_nonce<AccountId: Encode + Decode, Index: Encode + Decode>(
&self, at: &BlockId<Block>, account: &AccountId
) -> Result<Index, Self::Error> {
self.call_api_at(at, "account_nonce", &(account))
}
fn lookup_address<Address: Encode + Decode, AccountId: Encode + Decode>(
&self, at: &BlockId<Block>, address: &Address
) -> Result<Option<AccountId>, Self::Error> {
self.call_api_at(at, "lookup_address", &(address))
}
}
impl<B, E, Block> api::TaggedTransactionQueue<Block> for Client<B, E, Block> where impl<B, E, Block> api::TaggedTransactionQueue<Block> for Client<B, E, Block> where
B: backend::Backend<Block, Blake2Hasher>, B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>, E: CallExecutor<Block, Blake2Hasher>,
@@ -1176,30 +1141,6 @@ impl<B, E, Block> api::TaggedTransactionQueue<Block> for Client<B, E, Block> whe
} }
} }
impl<B, E, Block> api::Miscellaneous<Block> for Client<B, E, Block> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>,
Block: BlockT,
{
type Error = Error;
fn validator_count(&self, at: &BlockId<Block>) -> Result<u32, Self::Error> {
self.call_api_at(at, "validator_count", &())
}
fn validators<AccountId: Encode + Decode>(
&self, at: &BlockId<Block>
) -> Result<Vec<AccountId>, Self::Error> {
self.call_api_at(at, "validators", &())
}
fn timestamp<Moment: Encode + Decode>(
&self, at: &BlockId<Block>
) -> Result<Moment, Self::Error> {
self.call_api_at(at, "timestamp", &())
}
}
#[cfg(test)] #[cfg(test)]
pub(crate) mod tests { pub(crate) mod tests {
use std::collections::HashMap; use std::collections::HashMap;
@@ -1209,7 +1150,7 @@ pub(crate) mod tests {
use runtime_primitives::traits::{Digest as DigestT, DigestItem as DigestItemT}; use runtime_primitives::traits::{Digest as DigestT, DigestItem as DigestItemT};
use runtime_primitives::generic::DigestItem; use runtime_primitives::generic::DigestItem;
use test_client::{self, TestClient}; use test_client::{self, TestClient};
use test_client::client::BlockOrigin; use consensus::BlockOrigin;
use test_client::client::backend::Backend as TestBackend; use test_client::client::backend::Backend as TestBackend;
use test_client::BlockBuilderExt; use test_client::BlockBuilderExt;
use test_client::runtime::{self, Block, Transfer}; use test_client::runtime::{self, Block, Transfer};
+6
View File
@@ -16,11 +16,17 @@
//! Substrate client possible errors. //! Substrate client possible errors.
#![allow(missing_docs)]
use std; use std;
use state_machine; use state_machine;
use runtime_primitives::ApplyError; use runtime_primitives::ApplyError;
use consensus;
error_chain! { error_chain! {
links {
Consensus(consensus::Error, consensus::ErrorKind);
}
errors { errors {
/// Backend error. /// Backend error.
Backend(s: String) { Backend(s: String) {
+5 -2
View File
@@ -14,7 +14,9 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>. // along with Substrate. If not, see <http://www.gnu.org/licenses/>.
// tag::description[]
//! Substrate Client and associated logic. //! Substrate Client and associated logic.
// end::description[]
#![warn(missing_docs)] #![warn(missing_docs)]
#![recursion_limit="128"] #![recursion_limit="128"]
@@ -24,6 +26,7 @@ extern crate parity_codec as codec;
extern crate substrate_primitives as primitives; extern crate substrate_primitives as primitives;
extern crate sr_primitives as runtime_primitives; extern crate sr_primitives as runtime_primitives;
extern crate substrate_state_machine as state_machine; extern crate substrate_state_machine as state_machine;
extern crate substrate_consensus_common as consensus;
#[cfg(test)] extern crate substrate_keyring as keyring; #[cfg(test)] extern crate substrate_keyring as keyring;
#[cfg(test)] extern crate substrate_test_client as test_client; #[cfg(test)] extern crate substrate_test_client as test_client;
#[macro_use] extern crate substrate_telemetry; #[macro_use] extern crate substrate_telemetry;
@@ -61,8 +64,8 @@ pub use call_executor::{CallResult, CallExecutor, LocalCallExecutor};
pub use client::{ pub use client::{
new_with_backend, new_with_backend,
new_in_mem, new_in_mem,
BlockBody, BlockStatus, BlockOrigin, ImportNotifications, FinalityNotifications, BlockchainEvents, BlockBody, BlockStatus, ImportNotifications, FinalityNotifications, BlockchainEvents,
Client, ClientInfo, ChainHead, ImportResult, ImportBlock, Client, ClientInfo, ChainHead,
}; };
pub use notifications::{StorageEventStream, StorageChangeSet}; pub use notifications::{StorageEventStream, StorageChangeSet};
pub use state_machine::ExecutionStrategy; pub use state_machine::ExecutionStrategy;
+2 -1
View File
@@ -270,7 +270,8 @@ pub mod tests {
use error::Error as ClientError; use error::Error as ClientError;
use test_client::{self, TestClient}; use test_client::{self, TestClient};
use test_client::runtime::{self, Hash, Block, Header}; use test_client::runtime::{self, Hash, Block, Header};
use test_client::client::BlockOrigin; use consensus::BlockOrigin;
use in_mem::{Blockchain as InMemoryBlockchain}; use in_mem::{Blockchain as InMemoryBlockchain};
use light::fetcher::{Fetcher, FetchChecker, LightDataChecker, use light::fetcher::{Fetcher, FetchChecker, LightDataChecker,
RemoteCallRequest, RemoteHeaderRequest}; RemoteCallRequest, RemoteHeaderRequest};
+42
View File
@@ -0,0 +1,42 @@
[package]
name = "substrate-consensus-aura"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
description = "Rhododendron Round-Based consensus-algorithm for substrate"
[dependencies]
futures = "0.1.17"
parity-codec = { version = "2.1" }
substrate-consensus-common = { path = "../common" }
substrate-client = { path = "../../client" }
substrate-primitives = { path = "../../primitives" }
substrate-network = { path = "../../network" }
srml-support = { path = "../../../srml/support" }
sr-primitives = { path = "../../sr-primitives" }
sr-version = { path = "../../sr-version" }
sr-io = { path = "../../sr-io" }
srml-consensus = { path = "../../../srml/consensus" }
tokio = "0.1.7"
parking_lot = "0.4"
error-chain = "0.12"
log = "0.3"
[dev-dependencies]
substrate-keyring = { path = "../../keyring" }
substrate-executor = { path = "../../executor" }
substrate-service = { path = "../../service" }
substrate-test-client = { path = "../../test-client" }
env_logger = { version = "0.4" }
[target.'cfg(test)'.dependencies]
substrate-network = { path = "../../network", features = ["test-helpers"] }
[features]
default = ["std"]
std = [
"substrate-primitives/std",
"srml-support/std",
"sr-primitives/std",
"sr-version/std",
]
+560
View File
@@ -0,0 +1,560 @@
// Copyright 2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate 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.
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Aura (Authority-round) consensus in substrate.
//!
//! Aura works by having a list of authorities A who are expected to roughly
//! agree on the current time. Time is divided up into discrete slots of t
//! seconds each. For each slot s, the author of that slot is A[s % |A|].
//!
//! The author is allowed to issue one block but not more during that slot,
//! and it will be built upon the longest valid chain that has been seen.
//!
//! Blocks from future steps will be either deferred or rejected depending on how
//! far in the future they are.
extern crate parity_codec as codec;
extern crate substrate_consensus_common as consensus_common;
extern crate substrate_client as client;
extern crate substrate_primitives as primitives;
extern crate substrate_network as network;
extern crate srml_support as runtime_support;
extern crate sr_primitives as runtime_primitives;
extern crate sr_version as runtime_version;
extern crate sr_io as runtime_io;
extern crate tokio;
#[cfg(test)]
extern crate substrate_keyring as keyring;
#[cfg(test)]
extern crate substrate_service as service;
#[cfg(test)]
extern crate substrate_test_client as test_client;
#[cfg(test)]
extern crate env_logger;
extern crate parking_lot;
#[macro_use]
extern crate log;
extern crate futures;
use std::sync::Arc;
use std::time::{Duration, Instant};
use codec::Encode;
use consensus_common::{Authorities, BlockImport, Environment, Proposer};
use client::ChainHead;
use consensus_common::{ImportBlock, BlockOrigin};
use runtime_primitives::{generic, generic::BlockId};
use runtime_primitives::traits::{Block, Header, Digest, DigestItemFor};
use network::import_queue::{Verifier, BasicQueue};
use primitives::{AuthorityId, ed25519};
use futures::{Stream, Future, IntoFuture, future::{self, Either}};
use tokio::timer::Interval;
pub use consensus_common::SyncOracle;
/// A handle to the network. This is generally implemented by providing some
/// handle to a gossip service or similar.
///
/// Intended to be a lightweight handle such as an `Arc`.
pub trait Network: Clone {
/// A stream of input messages for a topic.
type In: Stream<Item=Vec<u8>,Error=()>;
/// Send a message at a specific round out.
fn send_message(&self, slot: u64, message: Vec<u8>);
}
/// Configuration for Aura consensus.
#[derive(Clone)]
pub struct Config {
/// The local authority keypair. Can be none if this is just an observer.
pub local_key: Option<Arc<ed25519::Pair>>,
/// The slot duration in seconds.
pub slot_duration: u64
}
/// Get slot author for given block along with authorities.
fn slot_author(slot_num: u64, authorities: &[AuthorityId]) -> Option<AuthorityId> {
if authorities.is_empty() { return None }
let idx = slot_num % (authorities.len() as u64);
assert!(idx <= usize::max_value() as u64,
"It is impossible to have a vector with length beyond the address space; qed");
let current_author = *authorities.get(idx as usize)
.expect("authorities not empty; index constrained to list length;\
this is a valid index; qed");
Some(current_author)
}
fn duration_now() -> Option<Duration> {
use std::time::SystemTime;
let now = SystemTime::now();
now.duration_since(SystemTime::UNIX_EPOCH).map_err(|e| {
warn!("Current time {:?} is before unix epoch. Something is wrong: {:?}", now, e);
}).ok()
}
/// Get the slot for now.
fn slot_now(slot_duration: u64) -> Option<u64> {
duration_now().map(|s| s.as_secs() / slot_duration)
}
/// A digest item which is usable with aura consensus.
pub trait CompatibleDigestItem: Sized {
/// Construct a digest item which is a slot number and a signature on the
/// hash.
fn aura_seal(slot_number: u64, signature: ed25519::Signature) -> Self;
/// If this item is an Aura seal, return the slot number and signature.
fn as_aura_seal(&self) -> Option<(u64, &ed25519::Signature)>;
}
impl CompatibleDigestItem for generic::DigestItem<primitives::H256, u64> {
/// Construct a digest item which is a slot number and a signature on the
/// hash.
fn aura_seal(slot_number: u64, signature: ed25519::Signature) -> Self {
generic::DigestItem::Seal(slot_number, signature)
}
/// If this item is an Aura seal, return the slot number and signature.
fn as_aura_seal(&self) -> Option<(u64, &ed25519::Signature)> {
match self {
generic::DigestItem::Seal(slot, ref sign) => Some((*slot, sign)),
_ => None
}
}
}
impl CompatibleDigestItem for generic::DigestItem<primitives::H256, primitives::AuthorityId> {
/// Construct a digest item which is a slot number and a signature on the
/// hash.
fn aura_seal(slot_number: u64, signature: ed25519::Signature) -> Self {
generic::DigestItem::Seal(slot_number, signature)
}
/// If this item is an Aura seal, return the slot number and signature.
fn as_aura_seal(&self) -> Option<(u64, &ed25519::Signature)> {
match self {
generic::DigestItem::Seal(slot, ref sign) => Some((*slot, sign)),
_ => None
}
}
}
/// Start the aura worker. This should be run in a tokio runtime.
pub fn start_aura<B, C, E, SO, Error>(
config: Config,
client: Arc<C>,
env: Arc<E>,
sync_oracle: SO,
)
-> impl Future<Item=(),Error=()> where
B: Block,
C: Authorities<B, Error=Error> + BlockImport<B, Error=Error> + ChainHead<B>,
E: Environment<B, Error=Error>,
E::Proposer: Proposer<B, Error=Error>,
SO: SyncOracle + Send + Clone,
DigestItemFor<B>: CompatibleDigestItem,
Error: ::std::error::Error + Send + 'static + From<::consensus_common::Error>,
{
let make_authorship = move || {
let config = config.clone();
let client = client.clone();
let env = env.clone();
let sync_oracle = sync_oracle.clone();
let local_keys = config.local_key.map(|pair| (pair.public(), pair));
let slot_duration = config.slot_duration;
let mut last_authored_slot = 0;
let next_slot_start = duration_now().map(|now| {
let remaining_full_secs = slot_duration - (now.as_secs() % slot_duration) - 1;
let remaining_nanos = 1_000_000_000 - now.subsec_nanos();
Instant::now() + Duration::new(remaining_full_secs, remaining_nanos)
}).unwrap_or_else(|| Instant::now());
Interval::new(next_slot_start, Duration::from_secs(slot_duration))
.filter(move |_| !sync_oracle.is_major_syncing()) // only propose when we are not syncing.
.filter_map(move |_| local_keys.clone()) // skip if not authoring.
.map_err(|e| debug!(target: "aura", "Faulty timer: {:?}", e))
.for_each(move |(public_key, key)| {
use futures::future;
let slot_num = match slot_now(slot_duration) {
Some(n) => n,
None => return Either::B(future::err(())),
};
if last_authored_slot >= slot_num { return Either::B(future::ok(())) }
last_authored_slot = slot_num;
let chain_head = match client.best_block_header() {
Ok(x) => x,
Err(e) => {
warn!(target:"aura", "Unable to author block in slot {}. no best block header: {:?}", slot_num, e);
return Either::B(future::ok(()))
}
};
let authorities = match client.authorities(&BlockId::Hash(chain_head.hash())){
Ok(authorities) => authorities,
Err(e) => {
warn!("Unable to fetch authorities at block {:?}: {:?}", chain_head.hash(), e);
return Either::B(future::ok(()));
}
};
let proposal_work = match slot_author(slot_num, &authorities) {
None => return Either::B(future::ok(())),
Some(author) => if author.0 == public_key.0 {
// we are the slot author. make a block and sign it.
let proposer = match env.init(&chain_head, &authorities, key.clone()) {
Ok(p) => p,
Err(e) => {
warn!("Unable to author block in slot {:?}: {:?}", slot_num, e);
return Either::B(future::ok(()))
}
};
proposer.propose().into_future()
} else {
return Either::B(future::ok(()));
}
};
let block_import = client.clone();
Either::A(proposal_work
.map(move |b| {
let (header, body) = b.deconstruct();
let pre_hash = header.hash();
let parent_hash = header.parent_hash().clone();
// sign the pre-sealed hash of the block and then
// add it to a digest item.
let to_sign = (slot_num, pre_hash).encode();
let signature = key.sign(&to_sign[..]);
let item = <DigestItemFor<B> as CompatibleDigestItem>::aura_seal(slot_num, signature);
let import_block = ImportBlock {
origin: BlockOrigin::Own,
header,
external_justification: Vec::new(),
post_runtime_digests: vec![item],
body: Some(body),
finalized: false,
auxiliary: Vec::new(),
};
if let Err(e) = block_import.import_block(import_block, None) {
warn!(target: "aura", "Error with block built on {:?}: {:?}", parent_hash, e);
}
})
.map_err(|e| warn!("Failed to construct block: {:?}", e))
)
})
};
future::loop_fn((), move |()| {
let authorship_task = ::std::panic::AssertUnwindSafe(make_authorship());
authorship_task.catch_unwind().then(|res| {
match res {
Ok(Ok(())) => (),
Ok(Err(())) => warn!("Aura authorship task terminated unexpectedly. Restarting"),
Err(e) => {
if let Some(s) = e.downcast_ref::<&'static str>() {
warn!("Aura authorship task panicked at {:?}", s);
}
warn!("Restarting Aura authorship task");
}
}
Ok(future::Loop::Continue(()))
})
})
}
// a header which has been checked
enum CheckedHeader<H> {
// a header which has slot in the future. this is the full header (not stripped)
// and the slot in which it should be processed.
Deferred(H, u64),
// a header which is fully checked, including signature. This is the pre-header
// accompanied by the seal components.
Checked(H, u64, ed25519::Signature),
}
/// check a header has been signed by the right key. If the slot is too far in the future, an error will be returned.
/// if it's successful, returns the pre-header, the slot number, and the signat.
//
// FIXME: needs misbehavior types - https://github.com/paritytech/substrate/issues/1018
fn check_header<B: Block>(slot_now: u64, mut header: B::Header, hash: B::Hash, authorities: &[AuthorityId])
-> Result<CheckedHeader<B::Header>, String>
where DigestItemFor<B>: CompatibleDigestItem
{
let digest_item = match header.digest_mut().pop() {
Some(x) => x,
None => return Err(format!("Header {:?} is unsealed", hash)),
};
let (slot_num, &sig) = match digest_item.as_aura_seal() {
Some(x) => x,
None => return Err(format!("Header {:?} is unsealed", hash)),
};
if slot_num > slot_now {
header.digest_mut().push(digest_item);
Ok(CheckedHeader::Deferred(header, slot_num))
} else {
// check the signature is valid under the expected authority and
// chain state.
let expected_author = match slot_author(slot_num, &authorities) {
None => return Err("Slot Author not found".to_string()),
Some(author) => author
};
let pre_hash = header.hash();
let to_sign = (slot_num, pre_hash).encode();
let public = ed25519::Public(expected_author.0);
if ed25519::verify_strong(&sig, &to_sign[..], public) {
Ok(CheckedHeader::Checked(header, slot_num, sig))
} else {
Err(format!("Bad signature on {:?}", hash))
}
}
}
/// A verifier for Aura blocks.
pub struct AuraVerifier<C> {
config: Config,
client: Arc<C>,
}
impl<B: Block, C> Verifier<B> for AuraVerifier<C> where
C: Authorities<B> + BlockImport<B> + Send + Sync,
DigestItemFor<B>: CompatibleDigestItem,
{
fn verify(
&self,
origin: BlockOrigin,
header: B::Header,
_justification: Vec<u8>,
body: Option<Vec<B::Extrinsic>>
) -> Result<(ImportBlock<B>, Option<Vec<AuthorityId>>), String> {
let slot_now = slot_now(self.config.slot_duration)
.ok_or("System time is before UnixTime?".to_owned())?;
let hash = header.hash();
let parent_hash = *header.parent_hash();
let authorities = self.client.authorities(&BlockId::Hash(parent_hash))
.map_err(|e| format!("Could not fetch authorities at {:?}: {:?}", parent_hash, e))?;
// we add one to allow for some small drift.
// FIXME: in the future, alter this queue to allow deferring of headers
// https://github.com/paritytech/substrate/issues/1019
let checked_header = check_header::<B>(slot_now + 1, header, hash, &authorities[..])?;
match checked_header {
CheckedHeader::Checked(pre_header, slot_num, sig) => {
let item = <DigestItemFor<B>>::aura_seal(slot_num, sig);
debug!(target: "aura", "Checked {:?}; importing.", pre_header);
let import_block = ImportBlock {
origin,
header: pre_header,
external_justification: Vec::new(),
post_runtime_digests: vec![item],
body,
finalized: false,
auxiliary: Vec::new(),
};
// FIXME: extract authorities - https://github.com/paritytech/substrate/issues/1019
Ok((import_block, None))
}
CheckedHeader::Deferred(a, b) => {
debug!(target: "aura", "Checking {:?} failed; {:?}, {:?}.", hash, a, b);
Err(format!("Header {:?} rejected: too far in the future", hash))
}
}
}
}
/// The Aura import queue type.
pub type AuraImportQueue<B, C> = BasicQueue<B, AuraVerifier<C>>;
/// Start an import queue for the Aura consensus algorithm.
pub fn import_queue<B, C>(config: Config, client: Arc<C>) -> AuraImportQueue<B, C> where
B: Block,
C: Authorities<B> + BlockImport<B> + Send + Sync,
DigestItemFor<B>: CompatibleDigestItem,
{
let verifier = Arc::new(AuraVerifier { config, client });
BasicQueue::new(verifier)
}
#[cfg(test)]
mod tests {
use super::*;
use consensus_common::NoNetwork as DummyOracle;
use network::test::*;
use network::test::{Block as TestBlock, PeersClient};
use runtime_primitives::traits::Block as BlockT;
use network::ProtocolConfig;
use parking_lot::Mutex;
use tokio::runtime::current_thread;
use keyring::Keyring;
use client::BlockchainEvents;
use test_client;
type Error = client::error::Error;
type TestClient = client::Client<test_client::Backend, test_client::Executor, TestBlock>;
struct DummyFactory(Arc<TestClient>);
struct DummyProposer(u64, Arc<TestClient>);
impl Environment<TestBlock> for DummyFactory {
type Proposer = DummyProposer;
type Error = Error;
fn init(&self, parent_header: &<TestBlock as BlockT>::Header, _authorities: &[AuthorityId], _sign_with: Arc<ed25519::Pair>)
-> Result<DummyProposer, Error>
{
Ok(DummyProposer(parent_header.number + 1, self.0.clone()))
}
}
impl Proposer<TestBlock> for DummyProposer {
type Error = Error;
type Create = Result<TestBlock, Error>;
fn propose(&self) -> Result<TestBlock, Error> {
self.1.new_block().unwrap().bake().map_err(|e| e.into())
}
}
const SLOT_DURATION: u64 = 1;
const TEST_ROUTING_INTERVAL: Duration = Duration::from_millis(50);
pub struct AuraTestNet {
peers: Vec<Arc<Peer<AuraVerifier<PeersClient>>>>,
started: bool
}
impl TestNetFactory for AuraTestNet {
type Verifier = AuraVerifier<PeersClient>;
/// Create new test network with peers and given config.
fn from_config(_config: &ProtocolConfig) -> Self {
AuraTestNet {
peers: Vec::new(),
started: false
}
}
fn make_verifier(&self, client: Arc<PeersClient>, _cfg: &ProtocolConfig)
-> Arc<Self::Verifier>
{
let config = Config { local_key: None, slot_duration: SLOT_DURATION };
Arc::new(AuraVerifier { client, config })
}
fn peer(&self, i: usize) -> &Peer<Self::Verifier> {
&self.peers[i]
}
fn peers(&self) -> &Vec<Arc<Peer<Self::Verifier>>> {
&self.peers
}
fn mut_peers<F: Fn(&mut Vec<Arc<Peer<Self::Verifier>>>)>(&mut self, closure: F ) {
closure(&mut self.peers);
}
fn started(&self) -> bool {
self.started
}
fn set_started(&mut self, new: bool) {
self.started = new;
}
}
#[test]
fn authoring_blocks() {
::env_logger::init().ok();
let mut net = AuraTestNet::new(3);
net.start();
let peers = &[
(0, Keyring::Alice),
(1, Keyring::Bob),
(2, Keyring::Charlie),
];
let net = Arc::new(Mutex::new(net));
let mut import_notifications = Vec::new();
let mut runtime = current_thread::Runtime::new().unwrap();
for (peer_id, key) in peers {
let mut client = net.lock().peer(*peer_id).client().clone();
let environ = Arc::new(DummyFactory(client.clone()));
import_notifications.push(
client.import_notification_stream()
.take_while(|n| {
Ok(!(n.origin != BlockOrigin::Own && n.header.number() < &5))
})
.for_each(move |_| Ok(()))
);
let aura = start_aura(
Config {
local_key: Some(Arc::new(key.clone().into())),
slot_duration: SLOT_DURATION
},
client,
environ.clone(),
DummyOracle,
);
runtime.spawn(aura);
}
// wait for all finalized on each.
let wait_for = ::futures::future::join_all(import_notifications)
.map(|_| ())
.map_err(|_| ());
let drive_to_completion = ::tokio::timer::Interval::new_interval(TEST_ROUTING_INTERVAL)
.for_each(move |_| {
net.lock().send_import_notifications();
net.lock().sync();
Ok(())
})
.map(|_| ())
.map_err(|_| ());
runtime.block_on(wait_for.select(drive_to_completion).map_err(|_| ())).unwrap();
}
}
@@ -6,4 +6,10 @@ description = "Common utilities for substrate consensus"
[dependencies] [dependencies]
substrate-primitives = { path= "../../primitives" } substrate-primitives = { path= "../../primitives" }
error-chain = "0.12"
futures = "0.1"
sr-version = { path = "../../sr-version" }
sr-primitives = { path = "../../sr-primitives" } sr-primitives = { path = "../../sr-primitives" }
tokio = "0.1.7"
parity-codec = "2.1"
parity-codec-derive = "2.0"
@@ -0,0 +1,12 @@
= Consensus Common
.Summary
[source, toml]
----
include::Cargo.toml[lines=2..5]
----
.Description
----
include::src/lib.rs[tag=description]
----
@@ -0,0 +1,104 @@
use primitives::AuthorityId;
use runtime_primitives::traits::{Block as BlockT, DigestItemFor};
use runtime_primitives::Justification;
/// Block import result.
#[derive(Debug)]
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,
}
/// Block data origin.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum BlockOrigin {
/// Genesis block built into the client.
Genesis,
/// Block is part of the initial sync with the network.
NetworkInitialSync,
/// Block was broadcasted on the network.
NetworkBroadcast,
/// Block that was received from the network and validated in the consensus process.
ConsensusBroadcast,
/// Block that was collated by this node.
Own,
/// Block was imported from a file.
File,
}
/// Data required to import a Block
pub struct ImportBlock<Block: BlockT> {
/// Origin of the Block
pub origin: BlockOrigin,
/// The header, without consensus post-digests applied. This should be in the same
/// state as it comes out of the runtime.
///
/// Consensus engines which alter the header (by adding post-runtime digests)
/// should strip those off in the initial verification process and pass them
/// via the `post_runtime_digests` field. During block authorship, they should
/// not be pushed to the header directly.
///
/// The reason for this distinction is so the header can be directly
/// re-executed in a runtime that checks digest equivalence -- the
/// post-runtime digests are pushed back on after.
pub header: Block::Header,
/// Justification provided for this block from the outside:.
pub external_justification: Justification,
/// Digest items that have been added after the runtime for external
/// work, like a consensus signature.
pub post_runtime_digests: Vec<DigestItemFor<Block>>,
/// Block's body
pub body: Option<Vec<Block::Extrinsic>>,
/// Is this block finalized already?
/// `true` implies instant finality.
pub finalized: bool,
/// Auxiliary consensus data produced by the block.
/// Contains a list of key-value pairs. If values are `None`, the keys
/// will be deleted.
pub auxiliary: Vec<(Vec<u8>, Option<Vec<u8>>)>,
}
impl<Block: BlockT> ImportBlock<Block> {
/// Deconstruct the justified header into parts.
pub fn into_inner(self)
-> (
BlockOrigin,
<Block as BlockT>::Header,
Justification,
Vec<DigestItemFor<Block>>,
Option<Vec<<Block as BlockT>::Extrinsic>>,
bool,
Vec<(Vec<u8>, Option<Vec<u8>>)>,
) {
(
self.origin,
self.header,
self.external_justification,
self.post_runtime_digests,
self.body,
self.finalized,
self.auxiliary,
)
}
}
/// Block import trait.
pub trait BlockImport<B: BlockT> {
type Error: ::std::error::Error + Send + 'static;
/// Import a Block alongside the new authorities valid form this block forward
fn import_block(&self,
block: ImportBlock<B>,
new_authorities: Option<Vec<AuthorityId>>
) -> Result<ImportResult, Self::Error>;
}
@@ -0,0 +1,88 @@
// Copyright 2017-2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate 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.
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Error types in Consensus
use runtime_version::RuntimeVersion;
error_chain! {
errors {
/// Missing state at block with given descriptor.
StateUnavailable(b: String) {
description("State missing at given block."),
display("State unavailable at block {}", b),
}
/// I/O terminated unexpectedly
IoTerminated {
description("I/O terminated unexpectedly."),
display("I/O terminated unexpectedly."),
}
/// Unable to schedule wakeup.
FaultyTimer(e: ::tokio::timer::Error) {
description("Timer error"),
display("Timer error: {}", e),
}
/// Unable to propose a block.
CannotPropose {
description("Unable to create block proposal."),
display("Unable to create block proposal."),
}
/// Error checking signature
InvalidSignature(s: ::primitives::ed25519::Signature, a: ::primitives::AuthorityId) {
description("Message signature is invalid"),
display("Message signature {:?} by {:?} is invalid.", s, a),
}
/// Account is not an authority.
InvalidAuthority(a: ::primitives::AuthorityId) {
description("Message sender is not a valid authority"),
display("Message sender {:?} is not a valid authority.", a),
}
/// Authoring interface does not match the runtime.
IncompatibleAuthoringRuntime(native: RuntimeVersion, on_chain: RuntimeVersion) {
description("Authoring for current runtime is not supported"),
display("Authoring for current runtime is not supported. Native ({}) cannot author for on-chain ({}).", native, on_chain),
}
/// Authoring interface does not match the runtime.
RuntimeVersionMissing {
description("Current runtime has no version"),
display("Authoring for current runtime is not supported since it has no version."),
}
/// Authoring interface does not match the runtime.
NativeRuntimeMissing {
description("This build has no native runtime"),
display("Authoring in current build is not supported since it has no runtime."),
}
/// Justification requirements not met.
InvalidJustification {
description("Invalid justification"),
display("Invalid justification."),
}
/// Some other error.
Other(e: Box<::std::error::Error + Send>) {
description("Other error")
display("Other error: {}", e.description())
}
}
}
@@ -18,11 +18,10 @@
use super::MAX_TRANSACTIONS_SIZE; use super::MAX_TRANSACTIONS_SIZE;
use codec::{Decode, Encode}; use codec::Encode;
use node_runtime::{Block as GenericBlock};
use node_primitives::{Hash, BlockNumber};
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As}; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As};
type BlockNumber = u64;
error_chain! { error_chain! {
errors { errors {
@@ -30,13 +29,13 @@ error_chain! {
description("Proposal provided not a block."), description("Proposal provided not a block."),
display("Proposal provided not a block."), display("Proposal provided not a block."),
} }
WrongParentHash(expected: Hash, got: Hash) { WrongParentHash(expected: String, got: String) {
description("Proposal had wrong parent hash."), description("Proposal had wrong parent hash."),
display("Proposal had wrong parent hash. Expected {:?}, got {:?}", expected, got), display("Proposal had wrong parent hash. Expected {:?}, got {:?}", expected, got),
} }
WrongNumber(expected: BlockNumber, got: BlockNumber) { WrongNumber(expected: BlockNumber, got: BlockNumber) {
description("Proposal had wrong number."), description("Proposal had wrong number."),
display("Proposal had wrong number. Expected {:?}, got {:?}", expected, got), display("Proposal had wrong number. Expected {}, got {}", expected, got),
} }
ProposalTooLarge(size: usize) { ProposalTooLarge(size: usize) {
description("Proposal exceeded the maximum size."), description("Proposal exceeded the maximum size."),
@@ -50,20 +49,17 @@ error_chain! {
/// Attempt to evaluate a substrate block as a node block, returning error /// Attempt to evaluate a substrate block as a node block, returning error
/// upon any initial validity checks failing. /// upon any initial validity checks failing.
pub fn evaluate_initial<Block: BlockT, Hash>( pub fn evaluate_initial<Block: BlockT>(
proposal: &Block, proposal: &Block,
parent_hash: &Hash, parent_hash: &<Block as BlockT>::Hash,
parent_number: <<Block as BlockT>::Header as HeaderT>::Number, parent_number: <<Block as BlockT>::Header as HeaderT>::Number,
) -> Result<()> ) -> Result<()> {
where
Hash: PartialEq<<<GenericBlock as BlockT>::Header as HeaderT>::Hash>,
Hash: Into<self::Hash> + Clone,
{
let encoded = Encode::encode(proposal); let encoded = Encode::encode(proposal);
let proposal = GenericBlock::decode(&mut &encoded[..]) let proposal = Block::decode(&mut &encoded[..])
.ok_or_else(|| ErrorKind::BadProposalFormat)?; .ok_or_else(|| ErrorKind::BadProposalFormat)?;
let transactions_size = proposal.extrinsics.iter().fold(0, |a, tx| { let transactions_size = proposal.extrinsics().iter().fold(0, |a, tx| {
a + Encode::encode(tx).len() a + Encode::encode(tx).len()
}); });
@@ -72,11 +68,14 @@ where
} }
if *parent_hash != *proposal.header().parent_hash() { if *parent_hash != *proposal.header().parent_hash() {
bail!(ErrorKind::WrongParentHash((*parent_hash).clone().into(), proposal.header.parent_hash)); bail!(ErrorKind::WrongParentHash(
format!("{:?}", *parent_hash),
format!("{:?}", proposal.header().parent_hash())
));
} }
if parent_number.as_() + 1 != *proposal.header().number() { if parent_number.as_() + 1 != proposal.header().number().as_() {
bail!(ErrorKind::WrongNumber(parent_number.as_() + 1, proposal.header.number)); bail!(ErrorKind::WrongNumber(parent_number.as_() + 1, proposal.header().number().as_()));
} }
Ok(()) Ok(())
+109 -11
View File
@@ -14,21 +14,119 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Substrate Consensus Common. If not, see <http://www.gnu.org/licenses/>. // along with Substrate Consensus Common. If not, see <http://www.gnu.org/licenses/>.
//! Tracks offline validators. // tag::description[]
//! Consensus basics and common features
// end::description[]
// This provides "unused" building blocks to other crates
#![allow(dead_code)] #![allow(dead_code)]
// our error-chain could potentially blow up otherwise
#![recursion_limit="128"]
extern crate substrate_primitives as primitives; extern crate substrate_primitives as primitives;
extern crate sr_primitives; extern crate futures;
extern crate sr_version as runtime_version;
extern crate sr_primitives as runtime_primitives;
extern crate tokio;
use sr_primitives::{generic::BlockId}; extern crate parity_codec as codec;
use sr_primitives::traits::{Block, Header}; #[macro_use]
use sr_primitives::Justification; extern crate parity_codec_derive;
use primitives::AuthorityId;
/// Block import trait. #[macro_use]
pub trait BlockImport<B: Block> { extern crate error_chain;
/// Import a block alongside its corresponding justification.
fn import_block(&self, block: B, justification: Justification, authorities: &[AuthorityId]) -> bool; use std::sync::Arc;
}
use primitives::{ed25519, AuthorityId};
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::Block;
use futures::prelude::*;
pub mod offline_tracker; pub mod offline_tracker;
pub mod error;
mod block_import;
pub mod evaluation;
// block size limit.
const MAX_TRANSACTIONS_SIZE: usize = 4 * 1024 * 1024;
pub use self::error::{Error, ErrorKind};
pub use block_import::{BlockImport, ImportBlock, BlockOrigin, ImportResult};
/// Trait for getting the authorities at a given block.
pub trait Authorities<B: Block> {
type Error: ::std::error::Error + Send + 'static; /// Get the authorities at the given block.
fn authorities(&self, at: &BlockId<B>) -> Result<Vec<AuthorityId>, Self::Error>;
}
/// Environment producer for a Consensus instance. Creates proposer instance and communication streams.
pub trait Environment<B: Block> {
/// The proposer type this creates.
type Proposer: Proposer<B>;
/// Error which can occur upon creation.
type Error: From<Error>;
/// Initialize the proposal logic on top of a specific header. Provide
/// the authorities at that header, and a local key to sign any additional
/// consensus messages with as well.
fn init(&self, parent_header: &B::Header, authorities: &[AuthorityId], sign_with: Arc<ed25519::Pair>)
-> Result<Self::Proposer, Self::Error>;
}
/// Logic for a proposer.
///
/// This will encapsulate creation and evaluation of proposals at a specific
/// block.
pub trait Proposer<B: Block> {
/// Error type which can occur when proposing or evaluating.
type Error: From<Error> + ::std::fmt::Debug + 'static;
/// Future that resolves to a committed proposal.
type Create: IntoFuture<Item=B,Error=Self::Error>;
/// Create a proposal.
fn propose(&self) -> Self::Create;
}
/// Inherent data to include in a block.
#[derive(Encode, Decode)]
pub struct InherentData {
/// Current timestamp.
pub timestamp: u64,
/// Indices of offline validators.
pub offline_indices: Vec<u32>,
}
impl InherentData {
/// Create a new `InherentData` instance.
pub fn new(timestamp: u64, offline_indices: Vec<u32>) -> Self {
Self {
timestamp,
offline_indices
}
}
}
/// An oracle for when major synchronization work is being undertaken.
///
/// Generally, consensus authoring work isn't undertaken while well behind
/// the head of the chain.
pub trait SyncOracle {
/// Whether the synchronization service is undergoing major sync.
/// Returns true if so.
fn is_major_syncing(&self) -> bool;
}
/// A synchronization oracle for when there is no network.
#[derive(Clone, Copy, Debug)]
pub struct NoNetwork;
impl SyncOracle for NoNetwork {
fn is_major_syncing(&self) -> bool { false }
}
impl<T: SyncOracle> SyncOracle for Arc<T> {
fn is_major_syncing(&self) -> bool {
T::is_major_syncing(&*self)
}
}
+10 -7
View File
@@ -6,30 +6,33 @@ description = "Rhododendron Round-Based consensus-algorithm for substrate"
[dependencies] [dependencies]
futures = "0.1.17" futures = "0.1.17"
parity-codec = { version = "1.1" } parity-codec = { version = "2.1" }
parity-codec-derive = { version = "2.0" } parity-codec-derive = { version = "2.0" }
substrate-primitives = { path = "../../primitives" } substrate-primitives = { path = "../../primitives" }
substrate-consensus-common = { path = "../common" }
substrate-client = { path = "../../client" }
substrate-transaction-pool = { path = "../../transaction-pool" }
srml-support = { path = "../../../srml/support" } srml-support = { path = "../../../srml/support" }
srml-system = { path = "../../../srml/system" }
srml-consensus = { path = "../../../srml/consensus" }
sr-primitives = { path = "../../sr-primitives" } sr-primitives = { path = "../../sr-primitives" }
sr-version = { path = "../../sr-version" } sr-version = { path = "../../sr-version" }
sr-io = { path = "../../sr-io" } sr-io = { path = "../../sr-io" }
srml-consensus = { path = "../../../srml/consensus" }
tokio = "0.1.7" tokio = "0.1.7"
parking_lot = "0.4" parking_lot = "0.4"
error-chain = "0.12" error-chain = "0.12"
log = "0.3" log = "0.4"
rhododendron = { git = "https://github.com/paritytech/rhododendron.git", features = ["codec"] } rhododendron = { version = "0.4.0", features = ["codec"] }
serde = { version = "1.0", features = ["derive"] } exit-future = "0.1"
[dev-dependencies] [dev-dependencies]
substrate-keyring = { path = "../../keyring" } substrate-keyring = { path = "../../keyring" }
substrate-executor = { path = "../../executor" } substrate-executor = { path = "../../executor" }
[features] [features]
default = ["std"] default = ["std"]
std = [ std = [
"serde/std",
"substrate-primitives/std", "substrate-primitives/std",
"srml-support/std", "srml-support/std",
"sr-primitives/std", "sr-primitives/std",
+12
View File
@@ -0,0 +1,12 @@
= Consensus Rhododendron (RHD)
.Summary
[source, toml]
----
include::Cargo.toml[lines=2..5]
----
.Description
----
include::src/lib.rs[tag=description]
----
+29 -66
View File
@@ -1,4 +1,4 @@
// Copyright 2017-2018 Parity Technologies (UK) Ltd. // Copyright 2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate. // This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify // Substrate is free software: you can redistribute it and/or modify
@@ -14,81 +14,44 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>. // along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Error types in the BFT service. //! Error types in the rhododendron Consensus service.
use runtime_version::RuntimeVersion; use consensus::error::{Error as CommonError, ErrorKind as CommonErrorKind};
use primitives::AuthorityId;
use client;
error_chain! { error_chain! {
links {
Client(client::error::Error, client::error::ErrorKind);
Common(CommonError, CommonErrorKind);
}
errors { errors {
/// Missing state at block with given descriptor. NotValidator(id: AuthorityId) {
StateUnavailable(b: String) { description("Local account ID not a validator at this block."),
description("State missing at given block."), display("Local account ID ({:?}) not a validator at this block.", id),
display("State unavailable at block {}", b),
} }
PrematureDestruction {
/// I/O terminated unexpectedly description("Proposer destroyed before finishing proposing or evaluating"),
IoTerminated { display("Proposer destroyed before finishing proposing or evaluating"),
description("I/O terminated unexpectedly."),
display("I/O terminated unexpectedly."),
} }
Timer(e: ::tokio::timer::Error) {
/// Unable to schedule wakeup. description("Failed to register or resolve async timer."),
FaultyTimer(e: ::tokio::timer::Error) { display("Timer failed: {}", e),
description("Timer error"),
display("Timer error: {}", e),
} }
Executor(e: ::futures::future::ExecuteErrorKind) {
/// Unable to propose a block. description("Unable to dispatch agreement future"),
CannotPropose { display("Unable to dispatch agreement future: {:?}", e),
description("Unable to create block proposal."),
display("Unable to create block proposal."),
}
/// Error checking signature
InvalidSignature(s: ::primitives::ed25519::Signature, a: ::primitives::AuthorityId) {
description("Message signature is invalid"),
display("Message signature {:?} by {:?} is invalid.", s, a),
}
/// Account is not an authority.
InvalidAuthority(a: ::primitives::AuthorityId) {
description("Message sender is not a valid authority"),
display("Message sender {:?} is not a valid authority.", a),
}
/// Authoring interface does not match the runtime.
IncompatibleAuthoringRuntime(native: RuntimeVersion, on_chain: RuntimeVersion) {
description("Authoring for current runtime is not supported"),
display("Authoring for current runtime is not supported. Native ({}) cannot author for on-chain ({}).", native, on_chain),
}
/// Authoring interface does not match the runtime.
RuntimeVersionMissing {
description("Current runtime has no version"),
display("Authoring for current runtime is not supported since it has no version."),
}
/// Authoring interface does not match the runtime.
NativeRuntimeMissing {
description("This build has no native runtime"),
display("Authoring in current build is not supported since it has no runtime."),
}
/// Justification requirements not met.
InvalidJustification {
description("Invalid justification"),
display("Invalid justification."),
}
/// Some other error.
Other(e: Box<::std::error::Error + Send>) {
description("Other error")
display("Other error: {}", e.description())
} }
} }
} }
impl From<::rhododendron::InputStreamConcluded> for Error { impl From<::rhododendron::InputStreamConcluded> for Error {
fn from(_: ::rhododendron::InputStreamConcluded) -> Error { fn from(_: ::rhododendron::InputStreamConcluded) -> Self {
ErrorKind::IoTerminated.into() CommonErrorKind::IoTerminated.into()
}
}
impl From<CommonErrorKind> for Error {
fn from(e: CommonErrorKind) -> Self {
CommonError::from(e).into()
} }
} }
File diff suppressed because it is too large Load Diff
@@ -22,12 +22,9 @@ use std::thread;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use std::sync::Arc; use std::sync::Arc;
use rhd::{self, BftService};
use client::{BlockchainEvents, ChainHead, BlockBody}; use client::{BlockchainEvents, ChainHead, BlockBody};
use ed25519;
use futures::prelude::*; use futures::prelude::*;
use transaction_pool::txpool::{Pool as TransactionPool, ChainApi as PoolChainApi}; use transaction_pool::txpool::{Pool as TransactionPool, ChainApi as PoolChainApi};
use primitives;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, BlockNumberToHash}; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, BlockNumberToHash};
use tokio::executor::current_thread::TaskExecutor as LocalThreadHandle; use tokio::executor::current_thread::TaskExecutor as LocalThreadHandle;
@@ -35,8 +32,11 @@ use tokio::runtime::TaskExecutor as ThreadPoolHandle;
use tokio::runtime::current_thread::Runtime as LocalRuntime; use tokio::runtime::current_thread::Runtime as LocalRuntime;
use tokio::timer::Interval; use tokio::timer::Interval;
use parking_lot::RwLock;
use consensus::offline_tracker::OfflineTracker;
use super::{Network, ProposerFactory, AuthoringApi}; use super::{Network, ProposerFactory, AuthoringApi};
use error; use {consensus, primitives, ed25519, error, BftService, LocalProposer};
const TIMER_DELAY_MS: u64 = 5000; const TIMER_DELAY_MS: u64 = 5000;
const TIMER_INTERVAL_MS: u64 = 500; const TIMER_INTERVAL_MS: u64 = 500;
@@ -47,11 +47,12 @@ fn start_bft<F, C, Block>(
header: <Block as BlockT>::Header, header: <Block as BlockT>::Header,
bft_service: Arc<BftService<Block, F, C>>, bft_service: Arc<BftService<Block, F, C>>,
) where ) where
F: rhd::Environment<Block> + 'static, F: consensus::Environment<Block> + 'static,
C: rhd::BlockImport<Block> + rhd::Authorities<Block> + 'static, C: consensus::BlockImport<Block> + consensus::Authorities<Block> + 'static,
F::Error: ::std::fmt::Debug, F::Error: ::std::fmt::Debug,
<F::Proposer as rhd::Proposer<Block>>::Error: ::std::fmt::Display + Into<error::Error>, <F::Proposer as consensus::Proposer<Block>>::Error: ::std::fmt::Display + Into<error::Error>,
<F as rhd::Environment<Block>>::Error: ::std::fmt::Display, <F as consensus::Environment<Block>>::Proposer : LocalProposer<Block>,
<F as consensus::Environment<Block>>::Error: ::std::fmt::Display,
Block: BlockT, Block: BlockT,
{ {
let mut handle = LocalThreadHandle::current(); let mut handle = LocalThreadHandle::current();
@@ -88,14 +89,12 @@ impl Service {
C: BlockchainEvents<<A as AuthoringApi>::Block> C: BlockchainEvents<<A as AuthoringApi>::Block>
+ ChainHead<<A as AuthoringApi>::Block> + ChainHead<<A as AuthoringApi>::Block>
+ BlockBody<<A as AuthoringApi>::Block>, + BlockBody<<A as AuthoringApi>::Block>,
C: bft::BlockImport<<A as AuthoringApi>::Block> C: consensus::BlockImport<<A as AuthoringApi>::Block>
+ bft::Authorities<<A as AuthoringApi>::Block> + Send + Sync + 'static, + consensus::Authorities<<A as AuthoringApi>::Block> + Send + Sync + 'static,
primitives::H256: From<<<A as AuthoringApi>::Block as BlockT>::Hash>, primitives::H256: From<<<A as AuthoringApi>::Block as BlockT>::Hash>,
<<A as AuthoringApi>::Block as BlockT>::Hash: PartialEq<primitives::H256> + PartialEq, <<A as AuthoringApi>::Block as BlockT>::Hash: PartialEq<primitives::H256> + PartialEq,
N: Network<Block = <A as AuthoringApi>::Block> + Send + 'static, N: Network<Block = <A as AuthoringApi>::Block> + Send + 'static,
{ {
use parking_lot::RwLock;
use super::OfflineTracker;
let (signal, exit) = ::exit_future::signal(); let (signal, exit) = ::exit_future::signal();
let thread = thread::spawn(move || { let thread = thread::spawn(move || {
+1 -1
View File
@@ -24,7 +24,7 @@
//! - execute_block(bytes) //! - execute_block(bytes)
//! - init_block(PrevBlock?) -> InProgressBlock //! - init_block(PrevBlock?) -> InProgressBlock
//! - add_transaction(InProgressBlock) -> InProgressBlock //! - add_transaction(InProgressBlock) -> InProgressBlock
//! I leave it as is for now as it might be removed before this is ever done. //! It is left as is for now as it might be removed before this is ever done.
// end::description[] // end::description[]
#![warn(missing_docs)] #![warn(missing_docs)]
@@ -196,13 +196,9 @@ impl<D: NativeExecutionDispatch> CodeExecutor<Blake2Hasher> for NativeExecutor<D
#[macro_export] #[macro_export]
macro_rules! native_executor_instance { macro_rules! native_executor_instance {
(pub $name:ident, $dispatcher:path, $version:path, $code:expr) => { ( $pub:vis $name:ident, $dispatcher:path, $version:path, $code:expr) => {
pub struct $name;
native_executor_instance!(IMPL $name, $dispatcher, $version, $code);
};
($name:ident, $dispatcher:path, $version:path, $code:expr) => {
/// A unit struct which implements `NativeExecutionDispatch` feeding in the hard-coded runtime. /// A unit struct which implements `NativeExecutionDispatch` feeding in the hard-coded runtime.
struct $name; $pub struct $name;
native_executor_instance!(IMPL $name, $dispatcher, $version, $code); native_executor_instance!(IMPL $name, $dispatcher, $version, $code);
}; };
(IMPL $name:ident, $dispatcher:path, $version:path, $code:expr) => { (IMPL $name:ident, $dispatcher:path, $version:path, $code:expr) => {
@@ -0,0 +1,12 @@
= Finality GRANDPA (aka SHAFT)
.Summary
[source, toml]
----
include::Cargo.toml[lines=2..5]
----
.Description
----
include::src/lib.rs[tag=description]
----
+15 -9
View File
@@ -14,9 +14,11 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>. // along with Substrate. If not, see <http://www.gnu.org/licenses/>.
// tag::description[]
//! Integration of the GRANDPA finality gadget into substrate. //! Integration of the GRANDPA finality gadget into substrate.
//! //!
//! This is a long-running future that produces finality notifications. //! This is a long-running future that produces finality notifications.
// end::description[]
extern crate finality_grandpa as grandpa; extern crate finality_grandpa as grandpa;
extern crate futures; extern crate futures;
@@ -45,11 +47,11 @@ use futures::stream::Fuse;
use futures::sync::mpsc; use futures::sync::mpsc;
use client::{Client, error::Error as ClientError, ImportNotifications, backend::Backend, CallExecutor}; use client::{Client, error::Error as ClientError, ImportNotifications, backend::Backend, CallExecutor};
use codec::{Encode, Decode}; use codec::{Encode, Decode};
use consensus_common::BlockImport; use consensus_common::{BlockImport, ImportBlock, ImportResult};
use runtime_primitives::traits::{ use runtime_primitives::traits::{
NumberFor, Block as BlockT, Header as HeaderT, DigestItemFor, NumberFor, Block as BlockT, Header as HeaderT, DigestItemFor,
}; };
use runtime_primitives::{generic::BlockId, Justification}; use runtime_primitives::generic::BlockId;
use substrate_primitives::{ed25519, AuthorityId, Blake2Hasher}; use substrate_primitives::{ed25519, AuthorityId, Blake2Hasher};
use tokio::timer::Interval; use tokio::timer::Interval;
@@ -702,21 +704,24 @@ pub struct GrandpaBlockImport<B, E, Block: BlockT> {
impl<B, E, Block: BlockT> BlockImport<Block> for GrandpaBlockImport<B, E, Block> where impl<B, E, Block: BlockT> BlockImport<Block> for GrandpaBlockImport<B, E, Block> where
B: Backend<Block, Blake2Hasher> + 'static, B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static, E: CallExecutor<Block, Blake2Hasher> + 'static + Clone,
DigestItemFor<Block>: CompatibleDigestItem<NumberFor<Block>>, DigestItemFor<Block>: CompatibleDigestItem<NumberFor<Block>>,
{ {
fn import_block(&self, block: Block, _justification: Justification, _authorities: &[AuthorityId]) -> bool { type Error = ClientError;
fn import_block(&self, block: ImportBlock<Block>, new_authorities: Option<Vec<AuthorityId>>)
-> Result<ImportResult, Self::Error>
{
use runtime_primitives::traits::Digest; use runtime_primitives::traits::Digest;
use authorities::PendingChange; use authorities::PendingChange;
let maybe_event = block.header().digest().logs().iter() let maybe_event = block.header.digest().logs().iter()
.filter_map(|log| log.scheduled_change()) .filter_map(|log| log.scheduled_change())
.next() .next()
.map(|change| (block.header().hash(), *block.header().number(), change)); .map(|change| (block.header.hash(), *block.header.number(), change));
// TODO [now]: use import-block trait for client when implemented let result = self.inner.import_block(block, new_authorities);
let result = self.inner.import_block(unimplemented!(), unimplemented!()).is_ok(); if let (true, Some((hash, number, change))) = (result.is_ok(), maybe_event) {
if let (true, Some((hash, number, change))) = (result, maybe_event) {
self.authority_set.add_pending_change(PendingChange { self.authority_set.add_pending_change(PendingChange {
next_authorities: change.next_authorities, next_authorities: change.next_authorities,
finalization_depth: number + change.delay, finalization_depth: number + change.delay,
@@ -726,6 +731,7 @@ impl<B, E, Block: BlockT> BlockImport<Block> for GrandpaBlockImport<B, E, Block>
// TODO [now]: write to DB, and what to do on failure? // TODO [now]: write to DB, and what to do on failure?
} }
result result
} }
} }
+1 -1
View File
@@ -15,7 +15,7 @@
// along with Substrate. If not, see <http://www.gnu.org/licenses/>. // along with Substrate. If not, see <http://www.gnu.org/licenses/>.
// tag::description[] // tag::description[]
//! Support code for the runtime. //! Support code for the runtime. A set of test accounts.
// end::description[] // end::description[]
#[macro_use] extern crate hex_literal; #[macro_use] extern crate hex_literal;
+1
View File
@@ -17,6 +17,7 @@ linked-hash-map = "0.5"
rustc-hex = "1.0" rustc-hex = "1.0"
rand = "0.5" rand = "0.5"
substrate-primitives = { path = "../../core/primitives" } substrate-primitives = { path = "../../core/primitives" }
substrate-consensus-common = { path = "../../core/consensus/common" }
substrate-client = { path = "../../core/client" } substrate-client = { path = "../../core/client" }
sr-primitives = { path = "../../core/sr-primitives" } sr-primitives = { path = "../../core/sr-primitives" }
parity-codec = "2.1" parity-codec = "2.1"
+9 -4
View File
@@ -16,10 +16,12 @@
//! Blockchain access trait //! Blockchain access trait
use client::{self, Client as SubstrateClient, ImportBlock, ImportResult, ClientInfo, BlockStatus, CallExecutor}; use client::{self, Client as SubstrateClient, ClientInfo, BlockStatus, CallExecutor};
use client::error::Error; use client::error::Error;
use consensus::BlockImport;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor}; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor};
use runtime_primitives::generic::BlockId; use runtime_primitives::generic::{BlockId};
use consensus::{ImportBlock, ImportResult};
use runtime_primitives::Justification; use runtime_primitives::Justification;
use primitives::{Blake2Hasher, AuthorityId}; use primitives::{Blake2Hasher, AuthorityId};
@@ -69,9 +71,12 @@ pub trait Client<Block: BlockT>: Send + Sync {
impl<B, E, Block> Client<Block> for SubstrateClient<B, E, Block> where impl<B, E, Block> Client<Block> for SubstrateClient<B, E, Block> where
B: client::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static, B: client::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static, E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
Block: BlockT, Self: BlockImport<Block, Error=Error>,
Block: BlockT
{
fn import(&self, block: ImportBlock<Block>, new_authorities: Option<Vec<AuthorityId>>)
-> Result<ImportResult, Error>
{ {
fn import(&self, block: ImportBlock<Block>, new_authorities: Option<Vec<AuthorityId>>) -> Result<ImportResult, Error> {
(self as &SubstrateClient<B, E, Block>).import_block(block, new_authorities) (self as &SubstrateClient<B, E, Block>).import_block(block, new_authorities)
} }
+4 -5
View File
@@ -28,8 +28,6 @@ use std::collections::{HashSet, VecDeque};
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use parking_lot::{Condvar, Mutex, RwLock}; use parking_lot::{Condvar, Mutex, RwLock};
pub use client::{BlockOrigin, ImportBlock, ImportResult};
use network_libp2p::{NodeIndex, Severity}; use network_libp2p::{NodeIndex, Severity};
use primitives::AuthorityId; use primitives::AuthorityId;
@@ -42,6 +40,9 @@ use protocol::Context;
use service::ExecuteInContext; use service::ExecuteInContext;
use sync::ChainSync; use sync::ChainSync;
pub use consensus::{ImportBlock, ImportResult, BlockOrigin};
#[cfg(any(test, feature = "test-helpers"))] #[cfg(any(test, feature = "test-helpers"))]
use std::cell::RefCell; use std::cell::RefCell;
@@ -428,7 +429,6 @@ fn import_single_block<B: BlockT, V: Verifier<B>>(
trace!(target: "sync", "Verifying {}({}) failed: {}", number, hash, msg); trace!(target: "sync", "Verifying {}({}) failed: {}", number, hash, msg);
} }
BlockImportError::VerificationFailed(peer, msg) BlockImportError::VerificationFailed(peer, msg)
})?; })?;
match chain.import(import_block, new_authorities) { match chain.import(import_block, new_authorities) {
@@ -552,7 +552,7 @@ impl<B: BlockT> Verifier<B> for PassThroughVerifier {
body, body,
finalized: self.0, finalized: self.0,
external_justification: justification, external_justification: justification,
internal_justification: vec![], post_runtime_digests: vec![],
auxiliary: Vec::new(), auxiliary: Vec::new(),
}, None)) }, None))
} }
@@ -615,7 +615,6 @@ pub mod tests {
use message; use message;
use test_client::{self, TestClient}; use test_client::{self, TestClient};
use test_client::runtime::{Block, Hash}; use test_client::runtime::{Block, Hash};
use on_demand::tests::DummyExecutor;
use runtime_primitives::generic::BlockId; use runtime_primitives::generic::BlockId;
use std::cell::Cell; use std::cell::Cell;
use super::*; use super::*;
+1
View File
@@ -28,6 +28,7 @@ extern crate substrate_primitives as primitives;
extern crate substrate_client as client; extern crate substrate_client as client;
extern crate sr_primitives as runtime_primitives; extern crate sr_primitives as runtime_primitives;
extern crate substrate_network_libp2p as network_libp2p; extern crate substrate_network_libp2p as network_libp2p;
extern crate substrate_consensus_common as consensus;
extern crate parity_codec as codec; extern crate parity_codec as codec;
extern crate futures; extern crate futures;
extern crate rustc_hex; extern crate rustc_hex;
+16 -16
View File
@@ -776,41 +776,41 @@ macro_rules! construct_simple_protocol {
fn on_connect( fn on_connect(
&mut self, &mut self,
ctx: &mut $crate::Context<$block>, _ctx: &mut $crate::Context<$block>,
who: $crate::NodeIndex, _who: $crate::NodeIndex,
status: $crate::StatusMessage<$block> _status: $crate::StatusMessage<$block>
) { ) {
$( self.$sub_protocol_name.on_connect(ctx, who, status); )* $( self.$sub_protocol_name.on_connect(_ctx, _who, _status); )*
} }
fn on_disconnect(&mut self, ctx: &mut $crate::Context<$block>, who: $crate::NodeIndex) { fn on_disconnect(&mut self, _ctx: &mut $crate::Context<$block>, _who: $crate::NodeIndex) {
$( self.$sub_protocol_name.on_disconnect(ctx, who); )* $( self.$sub_protocol_name.on_disconnect(_ctx, _who); )*
} }
fn on_message( fn on_message(
&mut self, &mut self,
ctx: &mut $crate::Context<$block>, _ctx: &mut $crate::Context<$block>,
who: $crate::NodeIndex, _who: $crate::NodeIndex,
message: &mut Option<$crate::message::Message<$block>> _message: &mut Option<$crate::message::Message<$block>>
) { ) {
$( self.$sub_protocol_name.on_message(ctx, who, message); )* $( self.$sub_protocol_name.on_message(_ctx, _who, _message); )*
} }
fn on_abort(&mut self) { fn on_abort(&mut self) {
$( self.$sub_protocol_name.on_abort(); )* $( self.$sub_protocol_name.on_abort(); )*
} }
fn maintain_peers(&mut self, ctx: &mut $crate::Context<$block>) { fn maintain_peers(&mut self, _ctx: &mut $crate::Context<$block>) {
$( self.$sub_protocol_name.maintain_peers(ctx); )* $( self.$sub_protocol_name.maintain_peers(_ctx); )*
} }
fn on_block_imported( fn on_block_imported(
&mut self, &mut self,
ctx: &mut $crate::Context<$block>, _ctx: &mut $crate::Context<$block>,
hash: <$block as $crate::BlockT>::Hash, _hash: <$block as $crate::BlockT>::Hash,
header: &<$block as $crate::BlockT>::Header _header: &<$block as $crate::BlockT>::Header
) { ) {
$( self.$sub_protocol_name.on_block_imported(ctx, hash, header); )* $( self.$sub_protocol_name.on_block_imported(_ctx, _hash, _header); )*
} }
} }
} }
+6
View File
@@ -181,6 +181,12 @@ impl<B: BlockT + 'static, S: Specialization<B>, H: ExHashT> Service<B, S, H> {
} }
} }
impl<B: BlockT + 'static, S: Specialization<B>, H: ExHashT> ::consensus::SyncOracle for Service<B, S, H> {
fn is_major_syncing(&self) -> bool {
self.handler.sync().read().status().is_major_syncing()
}
}
impl<B: BlockT + 'static, S: Specialization<B>, H:ExHashT> Drop for Service<B, S, H> { impl<B: BlockT + 'static, S: Specialization<B>, H:ExHashT> Drop for Service<B, S, H> {
fn drop(&mut self) { fn drop(&mut self) {
self.handler.stop(); self.handler.stop();
@@ -25,9 +25,6 @@ pub trait Specialization<B: BlockT>: Send + Sync + 'static {
/// Get the current specialization-status. /// Get the current specialization-status.
fn status(&self) -> Vec<u8>; fn status(&self) -> Vec<u8>;
/// Called on start-up.
fn on_start(&mut self) { }
/// Called when a peer successfully handshakes. /// Called when a peer successfully handshakes.
fn on_connect(&mut self, ctx: &mut Context<B>, who: NodeIndex, status: ::message::Status<B>); fn on_connect(&mut self, ctx: &mut Context<B>, who: NodeIndex, status: ::message::Status<B>);
+13 -1
View File
@@ -18,7 +18,8 @@ use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use protocol::Context; use protocol::Context;
use network_libp2p::{Severity, NodeIndex}; use network_libp2p::{Severity, NodeIndex};
use client::{BlockStatus, BlockOrigin, ClientInfo}; use client::{BlockStatus, ClientInfo};
use consensus::BlockOrigin;
use client::error::Error as ClientError; use client::error::Error as ClientError;
use blocks::{self, BlockCollection}; use blocks::{self, BlockCollection};
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, NumberFor}; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, NumberFor};
@@ -77,6 +78,17 @@ pub struct Status<B: BlockT> {
pub best_seen_block: Option<NumberFor<B>>, pub best_seen_block: Option<NumberFor<B>>,
} }
impl<B: BlockT> Status<B> {
/// Whether the synchronization status is doing major downloading work or
/// is near the head of the chain.
pub fn is_major_syncing(&self) -> bool {
match self.state {
SyncState::Idle => false,
SyncState::Downloading => true,
}
}
}
impl<B: BlockT> ChainSync<B> { impl<B: BlockT> ChainSync<B> {
/// Create a new instance. /// Create a new instance.
pub(crate) fn new(role: Roles, info: &ClientInfo<B>, import_queue: Arc<ImportQueue<B>>) -> Self { pub(crate) fn new(role: Roles, info: &ClientInfo<B>, import_queue: Arc<ImportQueue<B>>) -> Self {
+138 -61
View File
@@ -34,14 +34,16 @@ use service::TransactionPool;
use network_libp2p::{NodeIndex, PeerId, Severity}; use network_libp2p::{NodeIndex, PeerId, Severity};
use keyring::Keyring; use keyring::Keyring;
use codec::Encode; use codec::Encode;
use import_queue::{SyncImportQueue, PassThroughVerifier}; use import_queue::{SyncImportQueue, PassThroughVerifier, Verifier};
use test_client::{self, TestClient}; use consensus::BlockOrigin;
use specialization::Specialization; use specialization::Specialization;
use consensus_gossip::ConsensusGossip; use consensus_gossip::ConsensusGossip;
use import_queue::ImportQueue; use import_queue::ImportQueue;
use service::ExecuteInContext; use service::ExecuteInContext;
use test_client;
pub use test_client::runtime::{Block, Hash, Transfer, Extrinsic}; pub use test_client::runtime::{Block, Hash, Transfer, Extrinsic};
pub use test_client::TestClient;
struct DummyContextExecutor(Arc<Protocol<Block, DummySpecialization, Hash>>, Arc<RwLock<VecDeque<TestPacket>>>); struct DummyContextExecutor(Arc<Protocol<Block, DummySpecialization, Hash>>, Arc<RwLock<VecDeque<TestPacket>>>);
unsafe impl Send for DummyContextExecutor {} unsafe impl Send for DummyContextExecutor {}
@@ -135,20 +137,22 @@ pub struct TestPacket {
recipient: NodeIndex, recipient: NodeIndex,
} }
pub struct Peer { pub type PeersClient = client::Client<test_client::Backend, test_client::Executor, Block>;
client: Arc<client::Client<test_client::Backend, test_client::Executor, Block>>,
pub struct Peer<V: Verifier<Block>> {
client: Arc<PeersClient>,
pub sync: Arc<Protocol<Block, DummySpecialization, Hash>>, pub sync: Arc<Protocol<Block, DummySpecialization, Hash>>,
pub queue: Arc<RwLock<VecDeque<TestPacket>>>, pub queue: Arc<RwLock<VecDeque<TestPacket>>>,
import_queue: Arc<SyncImportQueue<Block, PassThroughVerifier>>, import_queue: Arc<SyncImportQueue<Block, V>>,
executor: Arc<DummyContextExecutor>, executor: Arc<DummyContextExecutor>,
} }
impl Peer { impl<V: 'static + Verifier<Block>> Peer<V> {
fn new( fn new(
client: Arc<client::Client<test_client::Backend, test_client::Executor, Block>>, client: Arc<PeersClient>,
sync: Arc<Protocol<Block, DummySpecialization, Hash>>, sync: Arc<Protocol<Block, DummySpecialization, Hash>>,
queue: Arc<RwLock<VecDeque<TestPacket>>>, queue: Arc<RwLock<VecDeque<TestPacket>>>,
import_queue: Arc<SyncImportQueue<Block, PassThroughVerifier>>, import_queue: Arc<SyncImportQueue<Block, V>>,
) -> Self { ) -> Self {
let executor = Arc::new(DummyContextExecutor(sync.clone(), queue.clone())); let executor = Arc::new(DummyContextExecutor(sync.clone(), queue.clone()));
Peer { client, sync, queue, import_queue, executor} Peer { client, sync, queue, import_queue, executor}
@@ -204,6 +208,13 @@ impl Peer {
self.sync.tick(&mut TestIo::new(&self.queue, None)); self.sync.tick(&mut TestIo::new(&self.queue, None));
} }
/// Send block import notifications.
fn send_import_notifications(&self) {
let info = self.client.info().expect("In-mem client does not fail");
let header = self.client.header(&BlockId::Hash(info.chain.best_hash)).unwrap().unwrap();
self.sync.on_block_imported(&mut TestIo::new(&self.queue, None), info.chain.best_hash, &header);
}
/// Restart sync for a peer. /// Restart sync for a peer.
fn restart_sync(&self) { fn restart_sync(&self) {
self.sync.abort(); self.sync.abort();
@@ -221,15 +232,18 @@ impl Peer {
} }
/// Add blocks to the peer -- edit the block before adding /// Add blocks to the peer -- edit the block before adding
pub fn generate_blocks<F>(&self, count: usize, mut edit_block: F) pub fn generate_blocks<F>(&self, count: usize, origin: BlockOrigin, mut edit_block: F)
where F: FnMut(&mut BlockBuilder<test_client::Backend, test_client::Executor, Block, Blake2Hasher>) where F: FnMut(&mut BlockBuilder<test_client::Backend, test_client::Executor, Block, Blake2Hasher>)
{ {
for _ in 0 .. count { for _ in 0 .. count {
let mut builder = self.client.new_block().unwrap(); let mut builder = self.client.new_block().unwrap();
edit_block(&mut builder); edit_block(&mut builder);
let block = builder.bake().unwrap(); let block = builder.bake().unwrap();
trace!("Generating {}, (#{}, parent={})", block.header.hash(), block.header.number, block.header.parent_hash); let hash = block.header.hash();
self.client.justify_and_import(client::BlockOrigin::File, block).unwrap(); trace!("Generating {}, (#{}, parent={})", hash, block.header.number, block.header.parent_hash);
let header = block.header.clone();
self.client.justify_and_import(origin, block).unwrap();
self.sync.on_block_imported(&mut TestIo::new(&self.queue, None), hash, &header);
} }
} }
@@ -237,7 +251,7 @@ impl Peer {
pub fn push_blocks(&self, count: usize, with_tx: bool) { pub fn push_blocks(&self, count: usize, with_tx: bool) {
let mut nonce = 0; let mut nonce = 0;
if with_tx { if with_tx {
self.generate_blocks(count, |builder| { self.generate_blocks(count, BlockOrigin::File, |builder| {
let transfer = Transfer { let transfer = Transfer {
from: Keyring::Alice.to_raw_public().into(), from: Keyring::Alice.to_raw_public().into(),
to: Keyring::Alice.to_raw_public().into(), to: Keyring::Alice.to_raw_public().into(),
@@ -249,7 +263,7 @@ impl Peer {
nonce = nonce + 1; nonce = nonce + 1;
}); });
} else { } else {
self.generate_blocks(count, |_| ()); self.generate_blocks(count, BlockOrigin::File, |_| ());
} }
} }
@@ -261,7 +275,7 @@ impl Peer {
} }
/// Get a reference to the client. /// Get a reference to the client.
pub fn client(&self) -> &Arc<client::Client<test_client::Backend, test_client::Executor, Block>> { pub fn client(&self) -> &Arc<PeersClient> {
&self.client &self.client
} }
} }
@@ -280,25 +294,30 @@ impl TransactionPool<Hash, Block> for EmptyTransactionPool {
fn on_broadcasted(&self, _: HashMap<Hash, Vec<String>>) {} fn on_broadcasted(&self, _: HashMap<Hash, Vec<String>>) {}
} }
pub struct TestNet { pub trait TestNetFactory: Sized {
peers: Vec<Arc<Peer>>, type Verifier: 'static + Verifier<Block>;
started: bool,
disconnect_events: Vec<(NodeIndex, NodeIndex)>, //disconnected (initiated by, to) /// These two need to be implemented!
fn from_config(config: &ProtocolConfig) -> Self;
fn make_verifier(&self, client: Arc<PeersClient>, config: &ProtocolConfig) -> Arc<Self::Verifier>;
/// Get reference to peer.
fn peer(&self, i: usize) -> &Peer<Self::Verifier>;
fn peers(&self) -> &Vec<Arc<Peer<Self::Verifier>>>;
fn mut_peers<F: Fn(&mut Vec<Arc<Peer<Self::Verifier>>>)>(&mut self, closure: F );
fn started(&self) -> bool;
fn set_started(&mut self, now: bool);
fn default_config() -> ProtocolConfig {
ProtocolConfig::default()
} }
impl TestNet {
/// Create new test network with this many peers. /// Create new test network with this many peers.
pub fn new(n: usize) -> Self { fn new(n: usize) -> Self {
Self::new_with_config(n, ProtocolConfig::default()) let config = Self::default_config();
} let mut net = Self::from_config(&config);
/// Create new test network with peers and given config.
pub fn new_with_config(n: usize, config: ProtocolConfig) -> Self {
let mut net = TestNet {
peers: Vec::new(),
started: false,
disconnect_events: Vec::new(),
};
for _ in 0..n { for _ in 0..n {
net.add_peer(&config); net.add_peer(&config);
@@ -307,10 +326,11 @@ impl TestNet {
} }
/// Add a peer. /// Add a peer.
pub fn add_peer(&mut self, config: &ProtocolConfig) { fn add_peer(&mut self, config: &ProtocolConfig) {
let client = Arc::new(test_client::new()); let client = Arc::new(test_client::new());
let tx_pool = Arc::new(EmptyTransactionPool); let tx_pool = Arc::new(EmptyTransactionPool);
let import_queue = Arc::new(SyncImportQueue::new(Arc::new(PassThroughVerifier(false)))); let verifier = self.make_verifier(client.clone(), config);
let import_queue = Arc::new(SyncImportQueue::new(verifier));
let specialization = DummySpecialization { let specialization = DummySpecialization {
gossip: ConsensusGossip::new(), gossip: ConsensusGossip::new(),
}; };
@@ -323,93 +343,107 @@ impl TestNet {
specialization specialization
).unwrap(); ).unwrap();
self.peers.push(Arc::new(Peer::new( let peer = Arc::new(Peer::new(
client, client,
Arc::new(sync), Arc::new(sync),
Arc::new(RwLock::new(VecDeque::new())), Arc::new(RwLock::new(VecDeque::new())),
import_queue import_queue
))); ));
}
/// Get reference to peer. self.mut_peers(|peers| {
pub fn peer(&self, i: usize) -> &Peer { peers.push(peer.clone())
&self.peers[i] });
} }
/// Start network. /// Start network.
fn start(&mut self) { fn start(&mut self) {
if self.started { if self.started() {
return; return;
} }
for peer in 0..self.peers.len() { self.mut_peers(|peers| {
self.peers[peer].start(); for peer in 0..peers.len() {
for client in 0..self.peers.len() { peers[peer].start();
for client in 0..peers.len() {
if peer != client { if peer != client {
self.peers[peer].on_connect(client as NodeIndex); peers[peer].on_connect(client as NodeIndex);
} }
} }
} }
self.started = true; });
self.set_started(true);
} }
/// Do one step of routing. /// Do one step of routing.
pub fn route(&mut self) { fn route(&mut self) {
for peer in 0..self.peers.len() { self.mut_peers(move |peers| {
let packet = self.peers[peer].pending_message(); for peer in 0..peers.len() {
let packet = peers[peer].pending_message();
if let Some(packet) = packet { if let Some(packet) = packet {
let disconnecting = { let disconnecting = {
let recipient = packet.recipient; let recipient = packet.recipient;
trace!("--- {} -> {} ---", peer, recipient); trace!(target: "sync", "--- {} -> {} ---", peer, recipient);
let to_disconnect = self.peers[recipient].receive_message(peer as NodeIndex, packet); let to_disconnect = peers[recipient].receive_message(peer as NodeIndex, packet);
for d in &to_disconnect { for d in &to_disconnect {
// notify this that disconnecting peers are disconnecting // notify this that disconnecting peers are disconnecting
self.peers[recipient].on_disconnect(*d as NodeIndex); peers[recipient].on_disconnect(*d as NodeIndex);
self.disconnect_events.push((peer, *d));
} }
to_disconnect to_disconnect
}; };
for d in &disconnecting { for d in &disconnecting {
// notify other peers that this peer is disconnecting // notify other peers that this peer is disconnecting
self.peers[*d].on_disconnect(peer as NodeIndex); peers[*d].on_disconnect(peer as NodeIndex);
} }
} }
} }
});
} }
/// Route messages between peers until all queues are empty. /// Route messages between peers until all queues are empty.
pub fn route_until_complete(&mut self) { fn route_until_complete(&mut self) {
while !self.done() { while !self.done() {
self.route() self.route()
} }
} }
/// Do a step of synchronization. /// Do a step of synchronization.
pub fn sync_step(&mut self) { fn sync_step(&mut self) {
self.route(); self.route();
for peer in &mut self.peers { self.mut_peers(|peers| {
for peer in peers {
peer.sync_step(); peer.sync_step();
} }
})
}
/// Send block import notifications for all peers.
fn send_import_notifications(&mut self) {
self.mut_peers(|peers| {
for peer in peers {
peer.send_import_notifications();
}
})
} }
/// Restart sync for a peer. /// Restart sync for a peer.
pub fn restart_peer(&mut self, i: usize) { fn restart_peer(&mut self, i: usize) {
self.peers[i].restart_sync(); self.peers()[i].restart_sync();
} }
/// Perform synchronization until complete. /// Perform synchronization until complete.
pub fn sync(&mut self) -> u32 { fn sync(&mut self) -> u32 {
self.start(); self.start();
let mut total_steps = 0; let mut total_steps = 0;
while !self.done() { while !self.done() {
self.sync_step(); self.sync_step();
total_steps += 1; total_steps += 1;
self.route();
} }
total_steps total_steps
} }
/// Do the given amount of sync steps. /// Do the given amount of sync steps.
pub fn sync_steps(&mut self, count: usize) { fn sync_steps(&mut self, count: usize) {
self.start(); self.start();
for _ in 0..count { for _ in 0..count {
self.sync_step(); self.sync_step();
@@ -417,7 +451,50 @@ impl TestNet {
} }
/// Whether all peers have synced. /// Whether all peers have synced.
pub fn done(&self) -> bool { fn done(&self) -> bool {
self.peers.iter().all(|p| p.is_done()) self.peers().iter().all(|p| p.is_done())
}
}
pub struct TestNet {
peers: Vec<Arc<Peer<PassThroughVerifier>>>,
started: bool
}
impl TestNetFactory for TestNet {
type Verifier = PassThroughVerifier;
/// Create new test network with peers and given config.
fn from_config(_config: &ProtocolConfig) -> Self {
TestNet {
peers: Vec::new(),
started: false
}
}
fn make_verifier(&self, _client: Arc<PeersClient>, _config: &ProtocolConfig)
-> Arc<Self::Verifier>
{
Arc::new(PassThroughVerifier(false))
}
fn peer(&self, i: usize) -> &Peer<Self::Verifier> {
&self.peers[i]
}
fn peers(&self) -> &Vec<Arc<Peer<Self::Verifier>>> {
&self.peers
}
fn mut_peers<F: Fn(&mut Vec<Arc<Peer<Self::Verifier>>>)>(&mut self, closure: F ) {
closure(&mut self.peers);
}
fn started(&self) -> bool {
self.started
}
fn set_started(&mut self, new: bool) {
self.started = new;
} }
} }
+16
View File
@@ -16,6 +16,7 @@
use client::backend::Backend; use client::backend::Backend;
use client::blockchain::HeaderBackend as BlockchainHeaderBackend; use client::blockchain::HeaderBackend as BlockchainHeaderBackend;
use consensus::BlockOrigin;
use sync::SyncState; use sync::SyncState;
use Roles; use Roles;
use super::*; use super::*;
@@ -68,6 +69,7 @@ fn sync_no_common_longer_chain_fails() {
fn sync_after_fork_works() { fn sync_after_fork_works() {
::env_logger::init().ok(); ::env_logger::init().ok();
let mut net = TestNet::new(3); let mut net = TestNet::new(3);
net.sync_step();
net.peer(0).push_blocks(30, false); net.peer(0).push_blocks(30, false);
net.peer(1).push_blocks(30, false); net.peer(1).push_blocks(30, false);
net.peer(2).push_blocks(30, false); net.peer(2).push_blocks(30, false);
@@ -87,6 +89,20 @@ fn sync_after_fork_works() {
assert!(net.peer(2).client.backend().blockchain().canon_equals_to(&peer1_chain)); assert!(net.peer(2).client.backend().blockchain().canon_equals_to(&peer1_chain));
} }
#[test]
fn own_blocks_are_announced() {
::env_logger::init().ok();
let mut net = TestNet::new(3);
net.sync(); // connect'em
net.peer(0).generate_blocks(1, BlockOrigin::Own, |_| ());
net.sync();
assert_eq!(net.peer(0).client.backend().blockchain().info().unwrap().best_number, 1);
assert_eq!(net.peer(1).client.backend().blockchain().info().unwrap().best_number, 1);
let peer0_chain = net.peer(0).client.backend().blockchain().clone();
assert!(net.peer(1).client.backend().blockchain().canon_equals_to(&peer0_chain));
assert!(net.peer(2).client.backend().blockchain().canon_equals_to(&peer0_chain));
}
#[test] #[test]
fn blocks_are_not_announced_by_light_nodes() { fn blocks_are_not_announced_by_light_nodes() {
::env_logger::init().ok(); ::env_logger::init().ok();
+4 -3
View File
@@ -31,7 +31,7 @@ pub type Signature = H512;
pub const PKCS_LEN: usize = 85; pub const PKCS_LEN: usize = 85;
/// A localized signature also contains sender information. /// A localized signature also contains sender information.
#[derive(PartialEq, Eq, Clone, Debug)] #[derive(PartialEq, Eq, Clone, Debug, Encode, Decode)]
pub struct LocalizedSignature { pub struct LocalizedSignature {
/// The signer of the signature. /// The signer of the signature.
pub signer: Public, pub signer: Public,
@@ -40,6 +40,7 @@ pub struct LocalizedSignature {
} }
/// Verify a message without type checking the parameters' types for the right size. /// Verify a message without type checking the parameters' types for the right size.
/// Returns true if the signature is good.
pub fn verify<P: AsRef<[u8]>>(sig: &[u8], message: &[u8], public: P) -> bool { pub fn verify<P: AsRef<[u8]>>(sig: &[u8], message: &[u8], public: P) -> bool {
let public_key = untrusted::Input::from(public.as_ref()); let public_key = untrusted::Input::from(public.as_ref());
let msg = untrusted::Input::from(message); let msg = untrusted::Input::from(message);
@@ -52,7 +53,7 @@ pub fn verify<P: AsRef<[u8]>>(sig: &[u8], message: &[u8], public: P) -> bool {
} }
/// A public key. /// A public key.
#[derive(PartialEq, Eq, Clone)] #[derive(PartialEq, Eq, Clone, Encode, Decode)]
pub struct Public(pub [u8; 32]); pub struct Public(pub [u8; 32]);
/// A key pair. /// A key pair.
@@ -246,7 +247,7 @@ impl Pair {
} }
} }
/// Verify a signature on a message. /// Verify a signature on a message. Returns true if the signature is good.
pub fn verify_strong<P: AsRef<Public>>(sig: &Signature, message: &[u8], pubkey: P) -> bool { pub fn verify_strong<P: AsRef<Public>>(sig: &Signature, message: &[u8], pubkey: P) -> bool {
let public_key = untrusted::Input::from(&pubkey.as_ref().0[..]); let public_key = untrusted::Input::from(&pubkey.as_ref().0[..]);
let msg = untrusted::Input::from(message); let msg = untrusted::Input::from(message);
+1
View File
@@ -22,5 +22,6 @@ tokio = "0.1.7"
[dev-dependencies] [dev-dependencies]
assert_matches = "1.1" assert_matches = "1.1"
substrate-test-client = { path = "../test-client" } substrate-test-client = { path = "../test-client" }
substrate-consensus-common = { path = "../consensus/common" }
rustc-hex = "2.0" rustc-hex = "2.0"
hex-literal = "0.1" hex-literal = "0.1"
+60 -1
View File
@@ -26,7 +26,7 @@ use rpc::futures::{stream, Future, Sink, Stream};
use runtime_primitives::generic::{BlockId, SignedBlock}; use runtime_primitives::generic::{BlockId, SignedBlock};
use runtime_primitives::traits::{Block as BlockT, Header, NumberFor}; use runtime_primitives::traits::{Block as BlockT, Header, NumberFor};
use runtime_version::RuntimeVersion; use runtime_version::RuntimeVersion;
use primitives::{Blake2Hasher}; use primitives::{Blake2Hasher, storage};
use subscriptions::Subscriptions; use subscriptions::Subscriptions;
@@ -68,6 +68,16 @@ build_rpc_trait! {
#[rpc(name = "chain_unsubscribeNewHead", alias = ["unsubscribe_newHead", ])] #[rpc(name = "chain_unsubscribeNewHead", alias = ["unsubscribe_newHead", ])]
fn unsubscribe_new_head(&self, SubscriptionId) -> RpcResult<bool>; fn unsubscribe_new_head(&self, SubscriptionId) -> RpcResult<bool>;
} }
#[pubsub(name = "chain_runtimeVersion")] {
/// New runtime version subscription
#[rpc(name = "chain_subscribeRuntimeVersion")]
fn subscribe_runtime_version(&self, Self::Metadata, pubsub::Subscriber<RuntimeVersion>);
/// Unsubscribe from runtime version subscription
#[rpc(name = "chain_unsubscribeRuntimeVersion")]
fn unsubscribe_runtime_version(&self, SubscriptionId) -> RpcResult<bool>;
}
} }
} }
@@ -163,4 +173,53 @@ impl<B, E, Block> ChainApi<Block::Hash, Block::Header, NumberFor<Block>, Block::
fn unsubscribe_new_head(&self, id: SubscriptionId) -> RpcResult<bool> { fn unsubscribe_new_head(&self, id: SubscriptionId) -> RpcResult<bool> {
Ok(self.subscriptions.cancel(id)) Ok(self.subscriptions.cancel(id))
} }
fn subscribe_runtime_version(&self, _meta: Self::Metadata, subscriber: pubsub::Subscriber<RuntimeVersion>) {
let stream = match self.client.storage_changes_notification_stream(Some(&[storage::StorageKey(storage::well_known_keys::CODE.to_vec())])) {
Ok(stream) => stream,
Err(err) => {
let _ = subscriber.reject(error::Error::from(err).into());
return;
}
};
self.subscriptions.add(subscriber, |sink| {
let version = self.runtime_version(None.into())
.map_err(Into::into);
let client = self.client.clone();
let mut previous_version = version.clone();
let stream = stream
.map_err(|e| warn!("Error creating storage notification stream: {:?}", e))
.filter_map(move |_| {
let version = client.info().and_then(|info| {
client.runtime_version_at(&BlockId::hash(info.chain.best_hash))
})
.map_err(error::Error::from)
.map_err(Into::into);
if previous_version != version {
previous_version = version.clone();
Some(version)
} else {
None
}
});
sink
.sink_map_err(|e| warn!("Error sending notifications: {:?}", e))
.send_all(
stream::iter_result(vec![Ok(version)])
.chain(stream)
)
// we ignore the resulting Stream (if the first stream is over we are unsubscribed)
.map(|_| ())
});
}
fn unsubscribe_runtime_version(&self, id: SubscriptionId) -> RpcResult<bool> {
Ok(self.subscriptions.cancel(id))
}
} }
+1 -1
View File
@@ -16,9 +16,9 @@
use super::*; use super::*;
use jsonrpc_macros::pubsub; use jsonrpc_macros::pubsub;
use client::BlockOrigin;
use test_client::{self, TestClient}; use test_client::{self, TestClient};
use test_client::runtime::{Block, Header}; use test_client::runtime::{Block, Header};
use consensus::BlockOrigin;
#[test] #[test]
fn should_return_header() { fn should_return_header() {
+2
View File
@@ -47,6 +47,8 @@ extern crate hex_literal;
#[cfg(test)] #[cfg(test)]
extern crate substrate_test_client as test_client; extern crate substrate_test_client as test_client;
#[cfg(test)] #[cfg(test)]
extern crate substrate_consensus_common as consensus;
#[cfg(test)]
extern crate rustc_hex; extern crate rustc_hex;
mod errors; mod errors;
+1 -1
View File
@@ -21,7 +21,7 @@ use std::{
sync::Arc, sync::Arc,
}; };
use client::{self, Client, CallExecutor, BlockchainEvents}; use client::{self, Client, CallExecutor, BlockchainEvents, runtime_api::Metadata};
use jsonrpc_macros::Trailing; use jsonrpc_macros::Trailing;
use jsonrpc_macros::pubsub; use jsonrpc_macros::pubsub;
use jsonrpc_pubsub::SubscriptionId; use jsonrpc_pubsub::SubscriptionId;
+1 -1
View File
@@ -17,7 +17,7 @@
use super::*; use super::*;
use self::error::{Error, ErrorKind}; use self::error::{Error, ErrorKind};
use client::BlockOrigin; use consensus::BlockOrigin;
use jsonrpc_macros::pubsub; use jsonrpc_macros::pubsub;
use rustc_hex::FromHex; use rustc_hex::FromHex;
use test_client::{self, runtime, keyring::Keyring, TestClient, BlockBuilderExt}; use test_client::{self, runtime, keyring::Keyring, TestClient, BlockBuilderExt};
+1
View File
@@ -20,6 +20,7 @@ substrate-keystore = { path = "../../core/keystore" }
sr-io = { path = "../../core/sr-io" } sr-io = { path = "../../core/sr-io" }
sr-primitives = { path = "../../core/sr-primitives" } sr-primitives = { path = "../../core/sr-primitives" }
substrate-primitives = { path = "../../core/primitives" } substrate-primitives = { path = "../../core/primitives" }
substrate-consensus-common = { path = "../../core/consensus/common" }
substrate-network = { path = "../../core/network" } substrate-network = { path = "../../core/network" }
substrate-client = { path = "../../core/client" } substrate-client = { path = "../../core/client" }
substrate-client-db = { path = "../../core/client/db" } substrate-client-db = { path = "../../core/client/db" }
+2 -1
View File
@@ -20,11 +20,12 @@ use std::{self, io::{Read, Write}};
use futures::Future; use futures::Future;
use serde_json; use serde_json;
use client::BlockOrigin;
use runtime_primitives::generic::{SignedBlock, BlockId}; use runtime_primitives::generic::{SignedBlock, BlockId};
use runtime_primitives::traits::{As, Block, Header}; use runtime_primitives::traits::{As, Block, Header};
use network::import_queue::{ImportQueue, Link, BlockData}; use network::import_queue::{ImportQueue, Link, BlockData};
use network::message; use network::message;
use consensus_common::BlockOrigin;
use components::{self, Components, ServiceFactory, FactoryFullConfiguration, FactoryBlockNumber, RuntimeGenesis}; use components::{self, Components, ServiceFactory, FactoryFullConfiguration, FactoryBlockNumber, RuntimeGenesis};
use new_client; use new_client;
use codec::{Decode, Encode}; use codec::{Decode, Encode};
+16 -9
View File
@@ -25,7 +25,7 @@ use chain_spec::ChainSpec;
use client_db; use client_db;
use client::{self, Client}; use client::{self, Client};
use {error, Service}; use {error, Service};
use network::{self, OnDemand}; use network::{self, OnDemand, import_queue::ImportQueue};
use substrate_executor::{NativeExecutor, NativeExecutionDispatch}; use substrate_executor::{NativeExecutor, NativeExecutionDispatch};
use transaction_pool::txpool::{self, Options as TransactionPoolOptions, Pool as TransactionPool}; use transaction_pool::txpool::{self, Options as TransactionPoolOptions, Pool as TransactionPool};
use runtime_primitives::{traits::Block as BlockT, traits::Header as HeaderT, BuildStorage}; use runtime_primitives::{traits::Block as BlockT, traits::Header as HeaderT, BuildStorage};
@@ -136,8 +136,10 @@ pub trait ServiceFactory: 'static + Sized {
type FullService: Deref<Target = Service<FullComponents<Self>>> + Send + Sync + 'static; type FullService: Deref<Target = Service<FullComponents<Self>>> + Send + Sync + 'static;
/// Extended light service type. /// Extended light service type.
type LightService: Deref<Target = Service<LightComponents<Self>>> + Send + Sync + 'static; type LightService: Deref<Target = Service<LightComponents<Self>>> + Send + Sync + 'static;
/// ImportQueue /// ImportQueue for full client
type ImportQueue: network::import_queue::ImportQueue<Self::Block> + 'static; type FullImportQueue: network::import_queue::ImportQueue<Self::Block> + 'static;
/// ImportQueue for light clients
type LightImportQueue: network::import_queue::ImportQueue<Self::Block> + 'static;
//TODO: replace these with a constructor trait. that TransactionPool implements. //TODO: replace these with a constructor trait. that TransactionPool implements.
/// Extrinsic pool constructor for the full client. /// Extrinsic pool constructor for the full client.
@@ -162,7 +164,7 @@ pub trait ServiceFactory: 'static + Sized {
fn build_full_import_queue( fn build_full_import_queue(
config: &FactoryFullConfiguration<Self>, config: &FactoryFullConfiguration<Self>,
_client: Arc<FullClient<Self>> _client: Arc<FullClient<Self>>
) -> Result<Self::ImportQueue, error::Error> { ) -> Result<Self::FullImportQueue, error::Error> {
if let Some(name) = config.chain_spec.consensus_engine() { if let Some(name) = config.chain_spec.consensus_engine() {
match name { match name {
_ => Err(format!("Chain Specification defines unknown consensus engine '{}'", name).into()) _ => Err(format!("Chain Specification defines unknown consensus engine '{}'", name).into())
@@ -177,7 +179,7 @@ pub trait ServiceFactory: 'static + Sized {
fn build_light_import_queue( fn build_light_import_queue(
config: &FactoryFullConfiguration<Self>, config: &FactoryFullConfiguration<Self>,
_client: Arc<LightClient<Self>> _client: Arc<LightClient<Self>>
) -> Result<Self::ImportQueue, error::Error> { ) -> Result<Self::LightImportQueue, error::Error> {
if let Some(name) = config.chain_spec.consensus_engine() { if let Some(name) = config.chain_spec.consensus_engine() {
match name { match name {
_ => Err(format!("Chain Specification defines unknown consensus engine '{}'", name).into()) _ => Err(format!("Chain Specification defines unknown consensus engine '{}'", name).into())
@@ -196,13 +198,16 @@ pub trait Components: 'static {
/// Client backend. /// Client backend.
type Backend: 'static + client::backend::Backend<FactoryBlock<Self::Factory>, Blake2Hasher>; type Backend: 'static + client::backend::Backend<FactoryBlock<Self::Factory>, Blake2Hasher>;
/// Client executor. /// Client executor.
type Executor: 'static + client::CallExecutor<FactoryBlock<Self::Factory>, Blake2Hasher> + Send + Sync; type Executor: 'static + client::CallExecutor<FactoryBlock<Self::Factory>, Blake2Hasher> + Send + Sync + Clone;
/// Extrinsic pool type. /// Extrinsic pool type.
type TransactionPoolApi: 'static + txpool::ChainApi< type TransactionPoolApi: 'static + txpool::ChainApi<
Hash = <<Self::Factory as ServiceFactory>::Block as BlockT>::Hash, Hash = <<Self::Factory as ServiceFactory>::Block as BlockT>::Hash,
Block = FactoryBlock<Self::Factory> Block = FactoryBlock<Self::Factory>
>; >;
/// Our Import Queue
type ImportQueue: ImportQueue<FactoryBlock<Self::Factory>> + 'static;
/// Create client. /// Create client.
fn build_client( fn build_client(
config: &FactoryFullConfiguration<Self::Factory>, config: &FactoryFullConfiguration<Self::Factory>,
@@ -221,7 +226,7 @@ pub trait Components: 'static {
fn build_import_queue( fn build_import_queue(
config: &FactoryFullConfiguration<Self::Factory>, config: &FactoryFullConfiguration<Self::Factory>,
client: Arc<ComponentClient<Self>> client: Arc<ComponentClient<Self>>
) -> Result<<Self::Factory as ServiceFactory>::ImportQueue, error::Error>; ) -> Result<Self::ImportQueue, error::Error>;
} }
/// A struct that implement `Components` for the full client. /// A struct that implement `Components` for the full client.
@@ -234,6 +239,7 @@ impl<Factory: ServiceFactory> Components for FullComponents<Factory> {
type Executor = FullExecutor<Factory>; type Executor = FullExecutor<Factory>;
type Backend = FullBackend<Factory>; type Backend = FullBackend<Factory>;
type TransactionPoolApi = <Factory as ServiceFactory>::FullTransactionPoolApi; type TransactionPoolApi = <Factory as ServiceFactory>::FullTransactionPoolApi;
type ImportQueue = Factory::FullImportQueue;
fn build_client( fn build_client(
config: &FactoryFullConfiguration<Factory>, config: &FactoryFullConfiguration<Factory>,
@@ -267,7 +273,7 @@ impl<Factory: ServiceFactory> Components for FullComponents<Factory> {
fn build_import_queue( fn build_import_queue(
config: &FactoryFullConfiguration<Self::Factory>, config: &FactoryFullConfiguration<Self::Factory>,
client: Arc<ComponentClient<Self>> client: Arc<ComponentClient<Self>>
) -> Result<<Self::Factory as ServiceFactory>::ImportQueue, error::Error> { ) -> Result<Self::ImportQueue, error::Error> {
Factory::build_full_import_queue(config, client) Factory::build_full_import_queue(config, client)
} }
} }
@@ -282,6 +288,7 @@ impl<Factory: ServiceFactory> Components for LightComponents<Factory> {
type Executor = LightExecutor<Factory>; type Executor = LightExecutor<Factory>;
type Backend = LightBackend<Factory>; type Backend = LightBackend<Factory>;
type TransactionPoolApi = <Factory as ServiceFactory>::LightTransactionPoolApi; type TransactionPoolApi = <Factory as ServiceFactory>::LightTransactionPoolApi;
type ImportQueue = <Factory as ServiceFactory>::LightImportQueue;
fn build_client( fn build_client(
config: &FactoryFullConfiguration<Factory>, config: &FactoryFullConfiguration<Factory>,
@@ -316,7 +323,7 @@ impl<Factory: ServiceFactory> Components for LightComponents<Factory> {
fn build_import_queue( fn build_import_queue(
config: &FactoryFullConfiguration<Self::Factory>, config: &FactoryFullConfiguration<Self::Factory>,
client: Arc<ComponentClient<Self>> client: Arc<ComponentClient<Self>>
) -> Result<<Self::Factory as ServiceFactory>::ImportQueue, error::Error> { ) -> Result<Self::ImportQueue, error::Error> {
Factory::build_light_import_queue(config, client) Factory::build_light_import_queue(config, client)
} }
} }
+263
View File
@@ -0,0 +1,263 @@
// Copyright 2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate 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.
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
//! provide consensus service to substrate.
// FIXME: move this into substrate-consensus-common - https://github.com/paritytech/substrate/issues/1021
use std::sync::Arc;
use std::time::{self, Duration, Instant};
use std;
use client::{self, error, Client as SubstrateClient, CallExecutor};
use client::runtime_api::{Core, BlockBuilder as BlockBuilderAPI, id::BLOCK_BUILDER};
use codec::{Decode, Encode};
use consensus_common::{self, InherentData, evaluation, offline_tracker::OfflineTracker};
use primitives::{AuthorityId, ed25519, Blake2Hasher};
use runtime_primitives::traits::{Block as BlockT, Hash as HashT, Header as HeaderT};
use runtime_primitives::generic::BlockId;
use transaction_pool::txpool::{self, Pool as TransactionPool};
use parking_lot::RwLock;
/// Shared offline validator tracker.
pub type SharedOfflineTracker = Arc<RwLock<OfflineTracker>>;
type Timestamp = u64;
// block size limit.
const MAX_TRANSACTIONS_SIZE: usize = 4 * 1024 * 1024;
/// Build new blocks.
pub trait BlockBuilder<Block: BlockT> {
/// Push an extrinsic onto the block. Fails if the extrinsic is invalid.
fn push_extrinsic(&mut self, extrinsic: <Block as BlockT>::Extrinsic) -> Result<(), error::Error>;
}
/// Local client abstraction for the consensus.
pub trait AuthoringApi:
Send
+ Sync
+ BlockBuilderAPI<<Self as AuthoringApi>::Block, Error=<Self as AuthoringApi>::Error>
+ Core<<Self as AuthoringApi>::Block, AuthorityId, Error=<Self as AuthoringApi>::Error>
{
/// The block used for this API type.
type Block: BlockT;
/// The error used by this API type.
type Error: std::error::Error;
/// Build a block on top of the given, with inherent extrinsics pre-pushed.
fn build_block<F: FnMut(&mut BlockBuilder<Self::Block>) -> ()>(
&self,
at: &BlockId<Self::Block>,
inherent_data: InherentData,
build_ctx: F,
) -> Result<Self::Block, error::Error>;
}
impl<'a, B, E, Block> BlockBuilder<Block> for client::block_builder::BlockBuilder<'a, B, E, Block, Blake2Hasher> where
B: client::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
Block: BlockT
{
fn push_extrinsic(&mut self, extrinsic: <Block as BlockT>::Extrinsic) -> Result<(), error::Error> {
client::block_builder::BlockBuilder::push(self, extrinsic).map_err(Into::into)
}
}
impl<'a, B, E, Block> AuthoringApi for SubstrateClient<B, E, Block> where
B: client::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
Block: BlockT,
{
type Block = Block;
type Error = client::error::Error;
fn build_block<F: FnMut(&mut BlockBuilder<Self::Block>) -> ()>(
&self,
at: &BlockId<Self::Block>,
inherent_data: InherentData,
mut build_ctx: F,
) -> Result<Self::Block, error::Error> {
let runtime_version = self.runtime_version_at(at)?;
let mut block_builder = self.new_block_at(at)?;
if runtime_version.has_api(BLOCK_BUILDER, 1) {
self.inherent_extrinsics(at, &inherent_data)?
.into_iter().try_for_each(|i| block_builder.push(i))?;
}
build_ctx(&mut block_builder);
block_builder.bake().map_err(Into::into)
}
}
/// Proposer factory.
pub struct ProposerFactory<C, A> where
C: AuthoringApi,
A: txpool::ChainApi,
{
/// The client instance.
pub client: Arc<C>,
/// The transaction pool.
pub transaction_pool: Arc<TransactionPool<A>>,
/// Offline-tracker.
pub offline: SharedOfflineTracker,
/// Force delay in evaluation this long.
pub force_delay: Timestamp,
}
impl<C, A> consensus_common::Environment<<C as AuthoringApi>::Block> for ProposerFactory<C, A> where
C: AuthoringApi,
A: txpool::ChainApi<Block=<C as AuthoringApi>::Block>,
client::error::Error: From<<C as AuthoringApi>::Error>
{
type Proposer = Proposer<C, A>;
type Error = error::Error;
fn init(
&self,
parent_header: &<<C as AuthoringApi>::Block as BlockT>::Header,
_: &[AuthorityId],
_: Arc<ed25519::Pair>,
) -> Result<Self::Proposer, error::Error> {
let parent_hash = parent_header.hash();
let id = BlockId::hash(parent_hash);
let authorities: Vec<AuthorityId> = self.client.authorities(&id)?;
self.offline.write().note_new_block(&authorities[..]);
info!("Starting consensus session on top of parent {:?}", parent_hash);
let now = Instant::now();
let proposer = Proposer {
client: self.client.clone(),
start: now,
parent_hash,
parent_id: id,
parent_number: *parent_header.number(),
transaction_pool: self.transaction_pool.clone(),
offline: self.offline.clone(),
authorities,
minimum_timestamp: current_timestamp() + self.force_delay,
};
Ok(proposer)
}
}
/// The proposer logic.
pub struct Proposer<C: AuthoringApi, A: txpool::ChainApi> {
client: Arc<C>,
start: Instant,
parent_hash: <<C as AuthoringApi>::Block as BlockT>::Hash,
parent_id: BlockId<<C as AuthoringApi>::Block>,
parent_number: <<<C as AuthoringApi>::Block as BlockT>::Header as HeaderT>::Number,
transaction_pool: Arc<TransactionPool<A>>,
offline: SharedOfflineTracker,
authorities: Vec<AuthorityId>,
minimum_timestamp: u64,
}
impl<C, A> consensus_common::Proposer<<C as AuthoringApi>::Block> for Proposer<C, A> where
C: AuthoringApi,
A: txpool::ChainApi<Block=<C as AuthoringApi>::Block>,
client::error::Error: From<<C as AuthoringApi>::Error>
{
type Create = Result<<C as AuthoringApi>::Block, error::Error>;
type Error = error::Error;
fn propose(&self) -> Result<<C as AuthoringApi>::Block, error::Error> {
use runtime_primitives::traits::BlakeTwo256;
const MAX_VOTE_OFFLINE_SECONDS: Duration = Duration::from_secs(60);
let timestamp = ::std::cmp::max(self.minimum_timestamp, current_timestamp());
let elapsed_since_start = self.start.elapsed();
let offline_indices = if elapsed_since_start > MAX_VOTE_OFFLINE_SECONDS {
Vec::new()
} else {
self.offline.read().reports(&self.authorities[..])
};
if !offline_indices.is_empty() {
info!("Submitting offline authorities {:?} for slash-vote",
offline_indices.iter().map(|&i| self.authorities[i as usize]).collect::<Vec<_>>(),
)
}
let inherent_data = InherentData {
timestamp,
offline_indices,
};
let block = self.client.build_block(
&self.parent_id,
inherent_data,
|block_builder| {
let mut unqueue_invalid = Vec::new();
let mut pending_size = 0;
let pending_iterator = self.transaction_pool.ready();
for pending in pending_iterator {
// TODO [ToDr] Probably get rid of it, and validate in runtime.
let encoded_size = pending.data.encode().len();
if pending_size + encoded_size >= MAX_TRANSACTIONS_SIZE { break }
match block_builder.push_extrinsic(pending.data.clone()) {
Ok(()) => {
pending_size += encoded_size;
}
Err(e) => {
trace!(target: "transaction-pool", "Invalid transaction: {}", e);
unqueue_invalid.push(pending.hash.clone());
}
}
}
self.transaction_pool.remove_invalid(&unqueue_invalid);
})?;
info!("Proposing block [number: {}; hash: {}; parent_hash: {}; extrinsics: [{}]]",
block.header().number(),
<<C as AuthoringApi>::Block as BlockT>::Hash::from(block.header().hash()),
block.header().parent_hash(),
block.extrinsics().iter()
.map(|xt| format!("{}", BlakeTwo256::hash_of(xt)))
.collect::<Vec<_>>()
.join(", ")
);
let substrate_block = Decode::decode(&mut block.encode().as_slice())
.expect("blocks are defined to serialize to substrate blocks correctly; qed");
assert!(evaluation::evaluate_initial(
&substrate_block,
&self.parent_hash,
self.parent_number,
).is_ok());
Ok(substrate_block)
}
}
fn current_timestamp() -> Timestamp {
time::SystemTime::now().duration_since(time::UNIX_EPOCH)
.expect("now always later than unix epoch; qed")
.as_secs()
}
+33 -9
View File
@@ -15,7 +15,7 @@
// along with Substrate. If not, see <http://www.gnu.org/licenses/>. // along with Substrate. If not, see <http://www.gnu.org/licenses/>.
// tag::description[] // tag::description[]
//! Substrate service. Starts a thread that spins the network, the client and the extrinsic pool. //! Substrate service. Starts a thread that spins up the network, client, and extrinsic pool.
//! Manages communication between them. //! Manages communication between them.
// end::description[] // end::description[]
@@ -29,6 +29,7 @@ extern crate parking_lot;
extern crate substrate_keystore as keystore; extern crate substrate_keystore as keystore;
extern crate substrate_primitives as primitives; extern crate substrate_primitives as primitives;
extern crate sr_primitives as runtime_primitives; extern crate sr_primitives as runtime_primitives;
extern crate substrate_consensus_common as consensus_common;
extern crate substrate_network as network; extern crate substrate_network as network;
extern crate substrate_executor; extern crate substrate_executor;
extern crate substrate_client as client; extern crate substrate_client as client;
@@ -56,6 +57,7 @@ mod error;
mod chain_spec; mod chain_spec;
pub mod config; pub mod config;
pub mod chain_ops; pub mod chain_ops;
pub mod consensus;
use std::io; use std::io;
use std::net::SocketAddr; use std::net::SocketAddr;
@@ -63,7 +65,7 @@ use std::collections::HashMap;
#[doc(hidden)] #[doc(hidden)]
pub use std::{ops::Deref, result::Result, sync::Arc}; pub use std::{ops::Deref, result::Result, sync::Arc};
use futures::prelude::*; use futures::prelude::*;
use parking_lot::Mutex; use parking_lot::{Mutex, RwLock};
use keystore::Store as Keystore; use keystore::Store as Keystore;
use client::BlockchainEvents; use client::BlockchainEvents;
use runtime_primitives::traits::{Header, As}; use runtime_primitives::traits::{Header, As};
@@ -80,6 +82,8 @@ pub use chain_spec::ChainSpec;
pub use transaction_pool::txpool::{self, Pool as TransactionPool, Options as TransactionPoolOptions, ChainApi, IntoPoolError}; pub use transaction_pool::txpool::{self, Pool as TransactionPool, Options as TransactionPoolOptions, ChainApi, IntoPoolError};
pub use client::ExecutionStrategy; pub use client::ExecutionStrategy;
use consensus_common::offline_tracker::OfflineTracker;
pub use consensus::ProposerFactory;
pub use components::{ServiceFactory, FullBackend, FullExecutor, LightBackend, pub use components::{ServiceFactory, FullBackend, FullExecutor, LightBackend,
LightExecutor, Components, PoolApi, ComponentClient, LightExecutor, Components, PoolApi, ComponentClient,
ComponentBlock, FullClient, LightClient, FullComponents, LightComponents, ComponentBlock, FullClient, LightClient, FullComponents, LightComponents,
@@ -98,6 +102,7 @@ pub struct Service<Components: components::Components> {
keystore: Keystore, keystore: Keystore,
exit: ::exit_future::Exit, exit: ::exit_future::Exit,
signal: Option<Signal>, signal: Option<Signal>,
proposer: Arc<ProposerFactory<ComponentClient<Components>, Components::TransactionPoolApi>>,
_rpc_http: Option<rpc::HttpServer>, _rpc_http: Option<rpc::HttpServer>,
_rpc_ws: Option<Mutex<rpc::WsServer>>, // WsServer is not `Sync`, but the service needs to be. _rpc_ws: Option<Mutex<rpc::WsServer>>, // WsServer is not `Sync`, but the service needs to be.
_telemetry: Option<tel::Telemetry>, _telemetry: Option<tel::Telemetry>,
@@ -118,6 +123,7 @@ pub fn new_client<Factory: components::ServiceFactory>(config: &FactoryFullConfi
impl<Components> Service<Components> impl<Components> Service<Components>
where where
Components: components::Components, Components: components::Components,
<Components as components::Components>::Executor: std::clone::Clone,
txpool::ExHash<Components::TransactionPoolApi>: serde::de::DeserializeOwned + serde::Serialize, txpool::ExHash<Components::TransactionPoolApi>: serde::de::DeserializeOwned + serde::Serialize,
txpool::ExtrinsicFor<Components::TransactionPoolApi>: serde::de::DeserializeOwned + serde::Serialize, txpool::ExtrinsicFor<Components::TransactionPoolApi>: serde::de::DeserializeOwned + serde::Serialize,
{ {
@@ -254,6 +260,13 @@ impl<Components> Service<Components>
) )
}; };
let proposer = Arc::new(ProposerFactory {
client: client.clone(),
transaction_pool: transaction_pool.clone(),
offline: Arc::new(RwLock::new(OfflineTracker::new())),
force_delay: 0 // FIXME: allow this to be configured
});
// Telemetry // Telemetry
let telemetry = match config.telemetry_url { let telemetry = match config.telemetry_url {
Some(url) => { Some(url) => {
@@ -287,6 +300,7 @@ impl<Components> Service<Components>
transaction_pool: transaction_pool, transaction_pool: transaction_pool,
signal: Some(signal), signal: Some(signal),
keystore: keystore, keystore: keystore,
proposer,
exit, exit,
_rpc_http: rpc_http, _rpc_http: rpc_http,
_rpc_ws: rpc_ws.map(Mutex::new), _rpc_ws: rpc_ws.map(Mutex::new),
@@ -303,6 +317,13 @@ impl<Components> Service<Components> where
self.client.clone() self.client.clone()
} }
/// Get shared proposer instance
pub fn proposer(&self)
-> Arc<ProposerFactory<ComponentClient<Components>, Components::TransactionPoolApi>>
{
self.proposer.clone()
}
/// Get shared network instance. /// Get shared network instance.
pub fn network(&self) -> Arc<components::NetworkService<Components::Factory>> { pub fn network(&self) -> Arc<components::NetworkService<Components::Factory>> {
self.network.as_ref().expect("self.network always Some").clone() self.network.as_ref().expect("self.network always Some").clone()
@@ -324,6 +345,7 @@ impl<Components> Service<Components> where
} }
} }
impl<Components> Drop for Service<Components> where Components: components::Components { impl<Components> Drop for Service<Components> where Components: components::Components {
fn drop(&mut self) { fn drop(&mut self) {
debug!(target: "service", "Substrate service shutdown"); debug!(target: "service", "Substrate service shutdown");
@@ -450,7 +472,7 @@ macro_rules! construct_simple_service {
$name: ident $name: ident
) => { ) => {
pub struct $name<C: $crate::Components> { pub struct $name<C: $crate::Components> {
inner: $crate::Service<C>, inner: $crate::Arc<$crate::Service<C>>,
} }
impl<C: $crate::Components> $name<C> { impl<C: $crate::Components> $name<C> {
@@ -460,7 +482,7 @@ macro_rules! construct_simple_service {
) -> $crate::Result<Self, $crate::Error> { ) -> $crate::Result<Self, $crate::Error> {
Ok( Ok(
Self { Self {
inner: $crate::Service::new(config, executor)? inner: $crate::Arc::new($crate::Service::new(config, executor)?)
} }
) )
} }
@@ -525,8 +547,9 @@ macro_rules! construct_service_factory {
Configuration = $config:ty, Configuration = $config:ty,
FullService = $full_service:ty { $( $full_service_init:tt )* }, FullService = $full_service:ty { $( $full_service_init:tt )* },
LightService = $light_service:ty { $( $light_service_init:tt )* }, LightService = $light_service:ty { $( $light_service_init:tt )* },
ImportQueue = $import_queue:ty FullImportQueue = $full_import_queue:ty
{ $( $full_import_queue_init:tt )* } { $( $full_import_queue_init:tt )* },
LightImportQueue = $light_import_queue:ty
{ $( $light_import_queue_init:tt )* }, { $( $light_import_queue_init:tt )* },
} }
) => { ) => {
@@ -544,7 +567,8 @@ macro_rules! construct_service_factory {
type Configuration = $config; type Configuration = $config;
type FullService = $full_service; type FullService = $full_service;
type LightService = $light_service; type LightService = $light_service;
type ImportQueue = $import_queue; type FullImportQueue = $full_import_queue;
type LightImportQueue = $light_import_queue;
fn build_full_transaction_pool( fn build_full_transaction_pool(
config: $crate::TransactionPoolOptions, config: $crate::TransactionPoolOptions,
@@ -571,14 +595,14 @@ macro_rules! construct_service_factory {
fn build_full_import_queue( fn build_full_import_queue(
config: &$crate::FactoryFullConfiguration<Self>, config: &$crate::FactoryFullConfiguration<Self>,
client: $crate::Arc<$crate::FullClient<Self>>, client: $crate::Arc<$crate::FullClient<Self>>,
) -> $crate::Result<Self::ImportQueue, $crate::Error> { ) -> $crate::Result<Self::FullImportQueue, $crate::Error> {
( $( $full_import_queue_init )* ) (config, client) ( $( $full_import_queue_init )* ) (config, client)
} }
fn build_light_import_queue( fn build_light_import_queue(
config: &FactoryFullConfiguration<Self>, config: &FactoryFullConfiguration<Self>,
client: Arc<$crate::LightClient<Self>>, client: Arc<$crate::LightClient<Self>>,
) -> Result<Self::ImportQueue, $crate::Error> { ) -> Result<Self::LightImportQueue, $crate::Error> {
( $( $light_import_queue_init )* ) (config, client) ( $( $light_import_queue_init )* ) (config, client)
} }
+1
View File
@@ -12,6 +12,7 @@ env_logger = "0.4"
fdlimit = "0.1" fdlimit = "0.1"
substrate-service = { path = "../../../core/service" } substrate-service = { path = "../../../core/service" }
substrate-network = { path = "../../../core/network" } substrate-network = { path = "../../../core/network" }
substrate-consensus-common = { path = "../../../core/consensus/common" }
substrate-primitives = { path = "../../../core/primitives" } substrate-primitives = { path = "../../../core/primitives" }
substrate-client = { path = "../../../core/client" } substrate-client = { path = "../../../core/client" }
sr-primitives = { path = "../../../core/sr-primitives" } sr-primitives = { path = "../../../core/sr-primitives" }
+2 -1
View File
@@ -27,6 +27,7 @@ extern crate substrate_service as service;
extern crate substrate_network as network; extern crate substrate_network as network;
extern crate substrate_primitives as primitives; extern crate substrate_primitives as primitives;
extern crate substrate_client as client; extern crate substrate_client as client;
extern crate substrate_consensus_common as consensus;
extern crate sr_primitives; extern crate sr_primitives;
use std::iter; use std::iter;
use std::sync::Arc; use std::sync::Arc;
@@ -47,9 +48,9 @@ use service::{
FactoryExtrinsic, FactoryExtrinsic,
}; };
use network::{NetworkConfiguration, NonReservedPeerMode, Protocol, SyncProvider, ManageNetwork}; use network::{NetworkConfiguration, NonReservedPeerMode, Protocol, SyncProvider, ManageNetwork};
use client::ImportBlock;
use sr_primitives::traits::As; use sr_primitives::traits::As;
use sr_primitives::generic::BlockId; use sr_primitives::generic::BlockId;
use consensus::{ImportBlock, BlockImport};
struct TestNet<F: ServiceFactory> { struct TestNet<F: ServiceFactory> {
runtime: Runtime, runtime: Runtime,
+12
View File
@@ -0,0 +1,12 @@
= Runtime API
.Summary
[source, toml]
----
include::Cargo.toml[lines=2..5]
----
.Description
----
include::src/lib.rs[tag=description]
----
+19 -10
View File
@@ -14,7 +14,9 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>. // along with Substrate. If not, see <http://www.gnu.org/licenses/>.
// tag::description[]
//! API's for interfacing with the runtime via native/wasm. //! API's for interfacing with the runtime via native/wasm.
// end::description[]
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
@@ -26,7 +28,7 @@ extern crate sr_version as runtime_version;
#[doc(hidden)] #[doc(hidden)]
pub use primitives::{traits::Block as BlockT, generic::BlockId, transaction_validity::TransactionValidity, ApplyResult}; pub use primitives::{traits::Block as BlockT, generic::BlockId, transaction_validity::TransactionValidity, ApplyResult};
use runtime_version::RuntimeVersion; use runtime_version::{ApiId, RuntimeVersion};
use rstd::vec::Vec; use rstd::vec::Vec;
#[doc(hidden)] #[doc(hidden)]
pub use rstd::slice; pub use rstd::slice;
@@ -427,6 +429,20 @@ macro_rules! decl_apis {
}; };
} }
/// The ApiIds for the various standard runtime APIs.
pub mod id {
use super::ApiId;
/// ApiId for the BlockBuilder trait.
pub const BLOCK_BUILDER: ApiId = *b"blkbuild";
/// ApiId for the TaggedTransactionQueue trait.
pub const TAGGED_TRANSACTION_QUEUE: ApiId = *b"validatx";
/// ApiId for the Metadata trait.
pub const METADATA: ApiId = *b"metadata";
}
decl_apis! { decl_apis! {
/// The `Core` api trait that is mandantory for each runtime. /// The `Core` api trait that is mandantory for each runtime.
pub trait Core<Block: BlockT, AuthorityId> { pub trait Core<Block: BlockT, AuthorityId> {
@@ -436,8 +452,8 @@ decl_apis! {
} }
/// The `Metadata` api trait that returns metadata for the runtime. /// The `Metadata` api trait that returns metadata for the runtime.
pub trait Metadata { pub trait Metadata<Data> {
fn metadata() -> Vec<u8>; fn metadata() -> Data;
} }
/// The `OldTxQueue` api trait for interfering with the old transaction queue. /// The `OldTxQueue` api trait for interfering with the old transaction queue.
@@ -451,13 +467,6 @@ decl_apis! {
fn validate_transaction<TransactionValidity>(tx: <Block as BlockT>::Extrinsic) -> TransactionValidity; fn validate_transaction<TransactionValidity>(tx: <Block as BlockT>::Extrinsic) -> TransactionValidity;
} }
/// The `Miscellaneous` api trait for getting miscellaneous information from the runtime.
pub trait Miscellaneous {
fn validator_count() -> u32;
fn validators<AccountId>() -> Vec<AccountId>;
fn timestamp<Moment>() -> Moment;
}
/// The `BlockBuilder` api trait that provides required functions for building a block for a runtime. /// The `BlockBuilder` api trait that provides required functions for building a block for a runtime.
pub trait BlockBuilder<Block: BlockT> ExtraClientSide <OverlayedChanges> { pub trait BlockBuilder<Block: BlockT> ExtraClientSide <OverlayedChanges> {
/// Initialise a block with the given header. /// Initialise a block with the given header.
+1
View File
@@ -31,3 +31,4 @@ std = [
"substrate-primitives/std", "substrate-primitives/std",
] ]
api-for-runtime = [] api-for-runtime = []
+12
View File
@@ -0,0 +1,12 @@
= Runtime Primitives
.Summary
[source, toml]
----
include::Cargo.toml[lines=2..5]
----
.Description
----
include::src/lib.rs[tag=description]
----
@@ -21,6 +21,8 @@ use rstd::prelude::*;
use codec::{Decode, Encode, Codec, Input}; use codec::{Decode, Encode, Codec, Input};
use traits::{self, Member, DigestItem as DigestItemT}; use traits::{self, Member, DigestItem as DigestItemT};
use substrate_primitives::hash::H512 as Signature;
#[derive(PartialEq, Eq, Clone, Encode, Decode)] #[derive(PartialEq, Eq, Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub struct Digest<Item> { pub struct Digest<Item> {
@@ -46,6 +48,10 @@ impl<Item> traits::Digest for Digest<Item> where
fn push(&mut self, item: Self::Item) { fn push(&mut self, item: Self::Item) {
self.logs.push(item); self.logs.push(item);
} }
fn pop(&mut self) -> Option<Self::Item> {
self.logs.pop()
}
} }
/// Digest item that is able to encode/decode 'system' digest items and /// Digest item that is able to encode/decode 'system' digest items and
@@ -60,10 +66,13 @@ pub enum DigestItem<Hash, AuthorityId> {
/// block. It is created for every block iff runtime supports changes /// block. It is created for every block iff runtime supports changes
/// trie creation. /// trie creation.
ChangesTrieRoot(Hash), ChangesTrieRoot(Hash),
/// Put a Seal on it
Seal(u64, Signature),
/// Any 'non-system' digest item, opaque to the native code. /// Any 'non-system' digest item, opaque to the native code.
Other(Vec<u8>), Other(Vec<u8>),
} }
/// A 'referencing view' for digest item. Does not own its contents. Used by /// A 'referencing view' for digest item. Does not own its contents. Used by
/// final runtime implementations for encoding/decoding its log items. /// final runtime implementations for encoding/decoding its log items.
#[derive(PartialEq, Eq, Clone)] #[derive(PartialEq, Eq, Clone)]
@@ -73,6 +82,9 @@ pub enum DigestItemRef<'a, Hash: 'a, AuthorityId: 'a> {
AuthoritiesChange(&'a [AuthorityId]), AuthoritiesChange(&'a [AuthorityId]),
/// Reference to `DigestItem::ChangesTrieRoot`. /// Reference to `DigestItem::ChangesTrieRoot`.
ChangesTrieRoot(&'a Hash), ChangesTrieRoot(&'a Hash),
/// A sealed signature for testing
Seal(&'a u64, &'a Signature),
/// Any 'non-system' digest item, opaque to the native code.
/// Reference to `DigestItem::Other`. /// Reference to `DigestItem::Other`.
Other(&'a Vec<u8>), Other(&'a Vec<u8>),
} }
@@ -87,6 +99,7 @@ enum DigestItemType {
Other = 0, Other = 0,
AuthoritiesChange, AuthoritiesChange,
ChangesTrieRoot, ChangesTrieRoot,
Seal,
} }
impl<Hash, AuthorityId> DigestItem<Hash, AuthorityId> { impl<Hash, AuthorityId> DigestItem<Hash, AuthorityId> {
@@ -103,6 +116,7 @@ impl<Hash, AuthorityId> DigestItem<Hash, AuthorityId> {
match *self { match *self {
DigestItem::AuthoritiesChange(ref v) => DigestItemRef::AuthoritiesChange(v), DigestItem::AuthoritiesChange(ref v) => DigestItemRef::AuthoritiesChange(v),
DigestItem::ChangesTrieRoot(ref v) => DigestItemRef::ChangesTrieRoot(v), DigestItem::ChangesTrieRoot(ref v) => DigestItemRef::ChangesTrieRoot(v),
DigestItem::Seal(ref v, ref s) => DigestItemRef::Seal(v, s),
DigestItem::Other(ref v) => DigestItemRef::Other(v), DigestItem::Other(ref v) => DigestItemRef::Other(v),
} }
} }
@@ -137,6 +151,10 @@ impl<Hash: Decode, AuthorityId: Decode> Decode for DigestItem<Hash, AuthorityId>
DigestItemType::ChangesTrieRoot => Some(DigestItem::ChangesTrieRoot( DigestItemType::ChangesTrieRoot => Some(DigestItem::ChangesTrieRoot(
Decode::decode(input)?, Decode::decode(input)?,
)), )),
DigestItemType::Seal => {
let vals: (u64, Signature) = Decode::decode(input)?;
Some(DigestItem::Seal(vals.0, vals.1))
},
DigestItemType::Other => Some(DigestItem::Other( DigestItemType::Other => Some(DigestItem::Other(
Decode::decode(input)?, Decode::decode(input)?,
)), )),
@@ -173,6 +191,10 @@ impl<'a, Hash: Encode, AuthorityId: Encode> Encode for DigestItemRef<'a, Hash, A
DigestItemType::ChangesTrieRoot.encode_to(&mut v); DigestItemType::ChangesTrieRoot.encode_to(&mut v);
changes_trie_root.encode_to(&mut v); changes_trie_root.encode_to(&mut v);
}, },
DigestItemRef::Seal(val, sig) => {
DigestItemType::Seal.encode_to(&mut v);
(val, sig).encode_to(&mut v);
},
DigestItemRef::Other(val) => { DigestItemRef::Other(val) => {
DigestItemType::Other.encode_to(&mut v); DigestItemType::Other.encode_to(&mut v);
val.encode_to(&mut v); val.encode_to(&mut v);
@@ -137,6 +137,7 @@ impl<Number, Hash, DigestItem> traits::Header for Header<Number, Hash, DigestIte
fn set_parent_hash(&mut self, hash: Self::Hash) { self.parent_hash = hash } fn set_parent_hash(&mut self, hash: Self::Hash) { self.parent_hash = hash }
fn digest(&self) -> &Self::Digest { &self.digest } fn digest(&self) -> &Self::Digest { &self.digest }
fn digest_mut(&mut self) -> &mut Self::Digest { &mut self.digest }
fn set_digest(&mut self, digest: Self::Digest) { self.digest = digest } fn set_digest(&mut self, digest: Self::Digest) { self.digest = digest }
fn new( fn new(
+2
View File
@@ -14,8 +14,10 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>. // along with Substrate. If not, see <http://www.gnu.org/licenses/>.
// tag::description[]
//! System manager: Handles all of the top-level stuff; executing block/transaction, setting code //! System manager: Handles all of the top-level stuff; executing block/transaction, setting code
//! and depositing logs. //! and depositing logs.
// end::description[]
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
@@ -42,6 +42,10 @@ impl traits::Digest for Digest {
fn push(&mut self, item: Self::Item) { fn push(&mut self, item: Self::Item) {
self.logs.push(item); self.logs.push(item);
} }
fn pop(&mut self) -> Option<Self::Item> {
self.logs.pop()
}
} }
#[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug, Encode, Decode)] #[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug, Encode, Decode)]
@@ -74,6 +78,7 @@ impl traits::Header for Header {
fn set_parent_hash(&mut self, hash: Self::Hash) { self.parent_hash = hash } fn set_parent_hash(&mut self, hash: Self::Hash) { self.parent_hash = hash }
fn digest(&self) -> &Self::Digest { &self.digest } fn digest(&self) -> &Self::Digest { &self.digest }
fn digest_mut(&mut self) -> &mut Self::Digest { &mut self.digest }
fn set_digest(&mut self, digest: Self::Digest) { self.digest = digest } fn set_digest(&mut self, digest: Self::Digest) { self.digest = digest }
fn new( fn new(
@@ -197,11 +197,13 @@ impl<T: Default + Eq + PartialEq> Clear for T {
pub trait SimpleBitOps: pub trait SimpleBitOps:
Sized + Clear + Sized + Clear +
rstd::ops::BitOr<Self, Output = Self> + rstd::ops::BitOr<Self, Output = Self> +
rstd::ops::BitXor<Self, Output = Self> +
rstd::ops::BitAnd<Self, Output = Self> rstd::ops::BitAnd<Self, Output = Self>
{} {}
impl<T: impl<T:
Sized + Clear + Sized + Clear +
rstd::ops::BitOr<Self, Output = Self> + rstd::ops::BitOr<Self, Output = Self> +
rstd::ops::BitXor<Self, Output = Self> +
rstd::ops::BitAnd<Self, Output = Self> rstd::ops::BitAnd<Self, Output = Self>
> SimpleBitOps for T {} > SimpleBitOps for T {}
@@ -429,6 +431,8 @@ pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebug + 'stat
fn set_parent_hash(&mut self, Self::Hash); fn set_parent_hash(&mut self, Self::Hash);
fn digest(&self) -> &Self::Digest; fn digest(&self) -> &Self::Digest;
/// Get a mutable reference to the digest.
fn digest_mut(&mut self) -> &mut Self::Digest;
fn set_digest(&mut self, Self::Digest); fn set_digest(&mut self, Self::Digest);
fn hash(&self) -> Self::Hash { fn hash(&self) -> Self::Hash {
@@ -520,6 +524,8 @@ pub trait Digest: Member + Default {
fn logs(&self) -> &[Self::Item]; fn logs(&self) -> &[Self::Item];
/// Push new digest item. /// Push new digest item.
fn push(&mut self, item: Self::Item); fn push(&mut self, item: Self::Item);
/// Pop a digest item.
fn pop(&mut self) -> Option<Self::Item>;
/// Get reference to the first digest item that matches the passed predicate. /// Get reference to the first digest item that matches the passed predicate.
fn log<T, F: Fn(&Self::Item) -> Option<&T>>(&self, predicate: F) -> Option<&T> { fn log<T, F: Fn(&Self::Item) -> Option<&T>>(&self, predicate: F) -> Option<&T> {
+13 -13
View File
@@ -15,25 +15,25 @@
// along with Substrate. If not, see <http://www.gnu.org/licenses/>. // along with Substrate. If not, see <http://www.gnu.org/licenses/>.
// tag::description[] // tag::description[]
//! This crate provides means of instantiation and execution of wasm modules. //! This crate provides means to instantiate and execute wasm modules.
//! //!
//! It works even when the user of this library is itself executes //! It works even when the user of this library executes from
//! inside the wasm VM. In this case same VM is used for execution //! inside the wasm VM. In this case the same VM is used for execution
//! of both the sandbox owner and the sandboxed module, without compromising security //! of both the sandbox owner and the sandboxed module, without compromising security
//! and without performance penalty of full wasm emulation inside wasm. //! and without the performance penalty of full wasm emulation inside wasm.
//! //!
//! This is achieved by using bindings to wasm VM which are published by the host API. //! This is achieved by using bindings to the wasm VM, which are published by the host API.
//! This API is thin and consists of only handful functions. It contains functions for instantiating //! This API is thin and consists of only a handful functions. It contains functions for instantiating
//! modules and executing them and for example doesn't contain functions for inspecting the module //! modules and executing them, but doesn't contain functions for inspecting the module
//! structure. The user of this library is supposed to read wasm module by it's own means. //! structure. The user of this library is supposed to read the wasm module.
//! //!
//! When this crate is used in `std` environment all these functions are implemented by directly //! When this crate is used in the `std` environment all these functions are implemented by directly
//! calling wasm VM. //! calling the wasm VM.
//! //!
//! Example of possible use-cases for this library are following: //! Example of possible use-cases for this library are the following:
//! //!
//! - implementing smart-contract runtimes which uses wasm for contract code //! - implementing smart-contract runtimes that use wasm for contract code
//! - executing wasm substrate runtime inside of a wasm parachain //! - executing a wasm substrate runtime inside of a wasm parachain
//! - etc //! - etc
// end::description[] // end::description[]
+13
View File
@@ -0,0 +1,13 @@
= Runtime Version
.Summary
[source, toml]
----
include::Cargo.toml[lines=2..5]
----
.Description
----
include::src/lib.rs[tag=description]
----
+3 -1
View File
@@ -14,7 +14,9 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>. // along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Version module for runtime; Provide a function that returns runtime version. // tag::description[]
//! Version module for the Substrate runtime; Provides a function that returns the runtime version.
// end::description[]
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
+4 -1
View File
@@ -64,6 +64,9 @@ pub use overlayed_changes::OverlayedChanges;
pub use trie_backend_essence::Storage; pub use trie_backend_essence::Storage;
pub use trie_backend::TrieBackend; pub use trie_backend::TrieBackend;
/// Default num of pages for the heap
const DEFAULT_HEAP_PAGES :u64 = 1024;
/// State Machine Error bound. /// State Machine Error bound.
/// ///
/// This should reflect WASM error type bound for future compatibility. /// This should reflect WASM error type bound for future compatibility.
@@ -291,7 +294,7 @@ where
.to_vec(); .to_vec();
let heap_pages = try_read_overlay_value(overlay, backend, well_known_keys::HEAP_PAGES)? let heap_pages = try_read_overlay_value(overlay, backend, well_known_keys::HEAP_PAGES)?
.and_then(|v| u64::decode(&mut &v[..])).unwrap_or(8) as usize; .and_then(|v| u64::decode(&mut &v[..])).unwrap_or(DEFAULT_HEAP_PAGES) as usize;
// read changes trie configuration. The reason why we're doing it here instead of the // read changes trie configuration. The reason why we're doing it here instead of the
// `OverlayedChanges` constructor is that we need proofs for this read as a part of // `OverlayedChanges` constructor is that we need proofs for this read as a part of
+1 -1
View File
@@ -17,7 +17,7 @@
// tag::description[] // tag::description[]
//! Telemetry utils. //! Telemetry utils.
//! //!
//! `telemetry` macro be used from whereever in the Substrate codebase //! `telemetry` macro may be used anywhere in the Substrate codebase
//! in order to send real-time logging information to the telemetry //! in order to send real-time logging information to the telemetry
//! server (if there is one). We use the async drain adapter of `slog` //! server (if there is one). We use the async drain adapter of `slog`
//! so that the logging thread doesn't get held up at all. //! so that the logging thread doesn't get held up at all.
+1
View File
@@ -7,6 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
substrate-client = { path = "../client" } substrate-client = { path = "../client" }
parity-codec = "2.1" parity-codec = "2.1"
substrate-executor = { path = "../executor" } substrate-executor = { path = "../executor" }
substrate-consensus-common = { path = "../consensus/common" }
substrate-keyring = { path = "../../core/keyring" } substrate-keyring = { path = "../../core/keyring" }
substrate-primitives = { path = "../primitives" } substrate-primitives = { path = "../primitives" }
substrate-test-runtime = { path = "../test-runtime" } substrate-test-runtime = { path = "../test-runtime" }
+12 -8
View File
@@ -16,15 +16,17 @@
//! Client extension for tests. //! Client extension for tests.
use client::{self, ImportBlock, Client}; use client::{self, Client};
use consensus::{ImportBlock, BlockImport, BlockOrigin};
use runtime_primitives::generic::BlockId; use runtime_primitives::generic::BlockId;
use primitives::Blake2Hasher; use primitives::Blake2Hasher;
use runtime; use runtime;
/// Extension trait for a test client. /// Extension trait for a test client.
pub trait TestClient { pub trait TestClient: Sized {
/// Justify and import block to the chain. No finality. /// Justify and import block to the chain. No finality.
fn justify_and_import(&self, origin: client::BlockOrigin, block: runtime::Block) -> client::error::Result<()>; fn justify_and_import(&self, origin: BlockOrigin, block: runtime::Block)
-> client::error::Result<()>;
/// Finalize a block. /// Finalize a block.
fn finalize_block(&self, id: BlockId<runtime::Block>) -> client::error::Result<()>; fn finalize_block(&self, id: BlockId<runtime::Block>) -> client::error::Result<()>;
@@ -36,21 +38,23 @@ pub trait TestClient {
impl<B, E> TestClient for Client<B, E, runtime::Block> impl<B, E> TestClient for Client<B, E, runtime::Block>
where where
B: client::backend::Backend<runtime::Block, Blake2Hasher>, B: client::backend::Backend<runtime::Block, Blake2Hasher>,
E: client::CallExecutor<runtime::Block, Blake2Hasher> E: client::CallExecutor<runtime::Block, Blake2Hasher>,
Self: BlockImport<runtime::Block, Error=client::error::Error>
{
fn justify_and_import(&self, origin: BlockOrigin, block: runtime::Block)
-> client::error::Result<()>
{ {
fn justify_and_import(&self, origin: client::BlockOrigin, block: runtime::Block) -> client::error::Result<()> {
let import = ImportBlock { let import = ImportBlock {
origin, origin,
header: block.header, header: block.header,
external_justification: vec![], external_justification: vec![],
internal_justification: vec![], post_runtime_digests: vec![],
body: Some(block.extrinsics), body: Some(block.extrinsics),
finalized: false, finalized: false,
auxiliary: Vec::new(), auxiliary: Vec::new(),
}; };
self.import_block(import, None)?;
Ok(()) self.import_block(import, None).map(|_| ())
} }
fn finalize_block(&self, id: BlockId<runtime::Block>) -> client::error::Result<()> { fn finalize_block(&self, id: BlockId<runtime::Block>) -> client::error::Result<()> {
+1
View File
@@ -28,6 +28,7 @@ extern crate sr_primitives as runtime_primitives;
pub extern crate substrate_client as client; pub extern crate substrate_client as client;
pub extern crate substrate_keyring as keyring; pub extern crate substrate_keyring as keyring;
pub extern crate substrate_test_runtime as runtime; pub extern crate substrate_test_runtime as runtime;
pub extern crate substrate_consensus_common as consensus;
pub mod client_ext; pub mod client_ext;
pub mod trait_tests; pub mod trait_tests;
@@ -21,7 +21,7 @@
use std::sync::Arc; use std::sync::Arc;
use keyring::Keyring; use keyring::Keyring;
use client::BlockOrigin; use consensus::BlockOrigin;
use primitives::Blake2Hasher; use primitives::Blake2Hasher;
use ::TestClient; use ::TestClient;
use runtime_primitives::traits::Block as BlockT; use runtime_primitives::traits::Block as BlockT;
@@ -0,0 +1,13 @@
= Transaction Pool
.Summary
[source, toml]
----
include::Cargo.toml[lines=2..5]
----
.Description
----
include::src/lib.rs[tag=description]
----
+12
View File
@@ -0,0 +1,12 @@
= Substrate Trie
.Summary
[source, toml]
----
include::Cargo.toml[lines=2..5]
----
.Description
----
include::src/lib.rs[tag=description]
----
-1
View File
@@ -1 +0,0 @@
This crate provides utility functions to interact with Substrate's Modified Merkle Patricia tree ("trie").
+3 -1
View File
@@ -14,7 +14,9 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Substrate-format Base-16 Modified Merkle Patricia Tree (Trie). // tag::description[]
//! Utility functions to interact with Substrate's Base-16 Modified Merkle Patricia tree ("trie").
// end::description[]
// TODO: no_std // TODO: no_std
-2
View File
@@ -3,8 +3,6 @@
:leveloffset: +3 :leveloffset: +3
include::../../safe-mix/README.adoc[]
include::../../subkey/README.adoc[] include::../../subkey/README.adoc[]
:leveloffset: -3 :leveloffset: -3
+28 -24
View File
@@ -1,62 +1,66 @@
== Substrate Packages == Substrate Packages
=== Substrate Core
:leveloffset: +3 :leveloffset: +3
include::../../core/bft/README.adoc[]
include::../../core/cli/README.adoc[]
include::../../core/client/README.adoc[] include::../../core/client/README.adoc[]
include::../../codec/README.adoc[] include::../../core/test-client/README.adoc[]
include::../../environmental/README.adoc[] include::../../core/client/db/README.adoc[]
include::../../core/state-db/README.adoc[]
include::../../core/consensus/common/README.adoc[]
include::../../core/consensus/rhd/README.adoc[]
include::../../core/executor/README.adoc[] include::../../core/executor/README.adoc[]
include::../../core/finality-grandpa/README.adoc[]
include::../../core/transaction-pool/README.adoc[] include::../../core/transaction-pool/README.adoc[]
include::../../core/keyring/README.adoc[] include::../../core/keyring/README.adoc[]
include::../../core/keystore/README.adoc[]
include::../../core/misbehavior-check/README.adoc[]
include::../../core/network/README.adoc[] include::../../core/network/README.adoc[]
include::../../core/network-libp2p/README.adoc[] include::../../core/network-libp2p/README.adoc[]
include::../../core/primitives/README.adoc[]
include::../../pwasm-alloc/README.adoc[]
include::../../core/rpc/README.adoc[] include::../../core/rpc/README.adoc[]
include::../../core/rpc-servers/README.adoc[] include::../../core/rpc-servers/README.adoc[]
include::../../srml/README.adoc[] include::../../srml/README.adoc[]
include::../../core/sr-api/README.adoc[]
include::../../core/sr-io/README.adoc[] include::../../core/sr-io/README.adoc[]
include::../../core/sr-primitives/README.adoc[]
include::../../core/sr-sandbox/README.adoc[] include::../../core/sr-sandbox/README.adoc[]
include::../../core/sr-std/README.adoc[] include::../../core/sr-std/README.adoc[]
include::../../core/runtime-support/README.adoc[]
include::../../core/serializer/README.adoc[]
include::../../core/service/README.adoc[]
include::../../core/state-db/README.adoc[]
include::../../core/state-machine/README.adoc[] include::../../core/state-machine/README.adoc[]
include::../../core/test-runtime/README.adoc[]
include::../../core/telemetry/README.adoc[] include::../../core/telemetry/README.adoc[]
include::../../core/test-client/README.adoc[] include::../../core/cli/README.adoc[]
include::../../core/test-srml/README.adoc[] include::../../core/service/README.adoc[]
include::../../core/trie/README.adoc[]
include::../../core/keystore/README.adoc[]
include::../../core/primitives/README.adoc[]
include::../../core/serializer/README.adoc[]
:leveloffset: -3 :leveloffset: -3
+6 -1
View File
@@ -9,14 +9,19 @@ log = "0.4"
tokio = "0.1.7" tokio = "0.1.7"
exit-future = "0.1" exit-future = "0.1"
substrate-cli = { path = "../../core/cli" } substrate-cli = { path = "../../core/cli" }
parity-codec = { version = "2.1" }
parking_lot = "0.4"
slog = "^2"
sr-io = { path = "../../core/sr-io" }
substrate-client = { path = "../../core/client" }
substrate-primitives = { path = "../../core/primitives" } substrate-primitives = { path = "../../core/primitives" }
node-runtime = { path = "../runtime" } node-runtime = { path = "../runtime" }
node-primitives = { path = "../primitives" } node-primitives = { path = "../primitives" }
node-network = { path = "../network" }
hex-literal = "0.1" hex-literal = "0.1"
substrate-service = { path = "../../core/service" } substrate-service = { path = "../../core/service" }
substrate-transaction-pool = { path = "../../core/transaction-pool" } substrate-transaction-pool = { path = "../../core/transaction-pool" }
substrate-network = { path = "../../core/network" } substrate-network = { path = "../../core/network" }
substrate-consensus-aura = { path = "../../core/consensus/aura" }
sr-primitives = { path = "../../core/sr-primitives" } sr-primitives = { path = "../../core/sr-primitives" }
node-executor = { path = "../executor" } node-executor = { path = "../executor" }
+16 -5
View File
@@ -17,8 +17,9 @@
//! Substrate chain configurations. //! Substrate chain configurations.
use primitives::{AuthorityId, ed25519}; use primitives::{AuthorityId, ed25519};
use node_primitives::AccountId;
use node_runtime::{GenesisConfig, ConsensusConfig, CouncilSeatsConfig, CouncilVotingConfig, DemocracyConfig, use node_runtime::{GenesisConfig, ConsensusConfig, CouncilSeatsConfig, CouncilVotingConfig, DemocracyConfig,
SessionConfig, StakingConfig, TimestampConfig, BalancesConfig, TreasuryConfig, SessionConfig, StakingConfig, TimestampConfig, BalancesConfig, TreasuryConfig, UpgradeKeyConfig,
ContractConfig, Permill, Perbill}; ContractConfig, Permill, Perbill};
use substrate_service; use substrate_service;
@@ -45,7 +46,7 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
const CENTS: u128 = 1_000 * MILLICENTS; // assume this is worth about a cent. const CENTS: u128 = 1_000 * MILLICENTS; // assume this is worth about a cent.
const DOLLARS: u128 = 100 * CENTS; const DOLLARS: u128 = 100 * CENTS;
const SECS_PER_BLOCK: u64 = 5; const SECS_PER_BLOCK: u64 = 4;
const MINUTES: u64 = 60 / SECS_PER_BLOCK; const MINUTES: u64 = 60 / SECS_PER_BLOCK;
const HOURS: u64 = MINUTES * 60; const HOURS: u64 = MINUTES * 60;
const DAYS: u64 = HOURS * 24; const DAYS: u64 = HOURS * 24;
@@ -121,6 +122,9 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
max_depth: 1024, max_depth: 1024,
block_gas_limit: 10_000_000, block_gas_limit: 10_000_000,
}), }),
upgrade_key: Some(UpgradeKeyConfig {
key: endowed_accounts[0].clone(),
}),
} }
} }
@@ -139,7 +143,7 @@ pub fn staging_testnet_config() -> ChainSpec {
) )
} }
fn testnet_genesis(initial_authorities: Vec<AuthorityId>) -> GenesisConfig { fn testnet_genesis(initial_authorities: Vec<AuthorityId>, upgrade_key: AccountId) -> GenesisConfig {
let endowed_accounts = vec![ let endowed_accounts = vec![
ed25519::Pair::from_seed(b"Alice ").public().0.into(), ed25519::Pair::from_seed(b"Alice ").public().0.into(),
ed25519::Pair::from_seed(b"Bob ").public().0.into(), ed25519::Pair::from_seed(b"Bob ").public().0.into(),
@@ -220,13 +224,18 @@ fn testnet_genesis(initial_authorities: Vec<AuthorityId>) -> GenesisConfig {
max_depth: 1024, max_depth: 1024,
block_gas_limit: 10_000_000, block_gas_limit: 10_000_000,
}), }),
upgrade_key: Some(UpgradeKeyConfig {
key: upgrade_key,
}),
} }
} }
fn development_config_genesis() -> GenesisConfig { fn development_config_genesis() -> GenesisConfig {
testnet_genesis(vec![ testnet_genesis(vec![
ed25519::Pair::from_seed(b"Alice ").public().into(), ed25519::Pair::from_seed(b"Alice ").public().into(),
]) ],
ed25519::Pair::from_seed(b"Alice ").public().0.into()
)
} }
/// Development config (single validator Alice) /// Development config (single validator Alice)
@@ -238,7 +247,9 @@ fn local_testnet_genesis() -> GenesisConfig {
testnet_genesis(vec![ testnet_genesis(vec![
ed25519::Pair::from_seed(b"Alice ").public().into(), ed25519::Pair::from_seed(b"Alice ").public().into(),
ed25519::Pair::from_seed(b"Bob ").public().into(), ed25519::Pair::from_seed(b"Bob ").public().into(),
]) ],
ed25519::Pair::from_seed(b"Alice ").public().0.into()
)
} }
/// Local testnet config (multivalidator Alice + Bob) /// Local testnet config (multivalidator Alice + Bob)
+2 -2
View File
@@ -30,9 +30,9 @@ extern crate hex_literal;
#[cfg(test)] #[cfg(test)]
extern crate substrate_service_test as service_test; extern crate substrate_service_test as service_test;
extern crate substrate_transaction_pool as transaction_pool; extern crate substrate_transaction_pool as transaction_pool;
#[macro_use]
extern crate substrate_network as network; extern crate substrate_network as network;
extern crate node_network; extern crate substrate_consensus_aura as consensus;
extern crate sr_primitives as runtime_primitives;
extern crate node_primitives; extern crate node_primitives;
#[macro_use] #[macro_use]
extern crate substrate_service; extern crate substrate_service;
+45 -31
View File
@@ -22,38 +22,19 @@ use std::sync::Arc;
use transaction_pool::{self, txpool::{Pool as TransactionPool}}; use transaction_pool::{self, txpool::{Pool as TransactionPool}};
use node_primitives::Block; use node_primitives::Block;
use node_runtime::GenesisConfig; use node_runtime::GenesisConfig;
use node_network::Protocol as NodeProtocol;
use substrate_service::{ use substrate_service::{
FactoryFullConfiguration, LightComponents, FullComponents, FullBackend, FactoryFullConfiguration, LightComponents, FullComponents, FullBackend,
LightBackend, FullExecutor, LightExecutor FullClient, LightClient, LightBackend, FullExecutor, LightExecutor,
Roles, TaskExecutor,
}; };
use network::import_queue::{BasicQueue, BlockOrigin, ImportBlock, Verifier};
use runtime_primitives::{traits::Block as BlockT};
use primitives::AuthorityId;
use node_executor; use node_executor;
use consensus::{import_queue, start_aura, Config as AuraConfig, AuraImportQueue};
// TODO: Remove me, when we have a functional consensus. const AURA_SLOT_DURATION: u64 = 6;
/// A verifier that doesn't actually do any checks
pub struct NoneVerifier; construct_simple_protocol! {
/// This Verifiyer accepts all data as valid /// Demo protocol attachment for substrate.
impl<B: BlockT> Verifier<B> for NoneVerifier { pub struct NodeProtocol where Block = Block { }
fn verify(
&self,
origin: BlockOrigin,
header: B::Header,
justification: Vec<u8>,
body: Option<Vec<B::Extrinsic>>
) -> Result<(ImportBlock<B>, Option<Vec<AuthorityId>>), String> {
Ok((ImportBlock {
origin,
header,
body,
finalized: true,
external_justification: justification,
internal_justification: vec![],
auxiliary: Vec::new(),
}, None))
}
} }
construct_simple_service!(Service); construct_simple_service!(Service);
@@ -70,15 +51,48 @@ construct_service_factory! {
Genesis = GenesisConfig, Genesis = GenesisConfig,
Configuration = (), Configuration = (),
FullService = Service<FullComponents<Self>> FullService = Service<FullComponents<Self>>
{ |config, executor| Service::<FullComponents<Factory>>::new(config, executor) }, { |config: FactoryFullConfiguration<Self>, executor: TaskExecutor| {
let is_auth = config.roles == Roles::AUTHORITY;
Service::<FullComponents<Factory>>::new(config, executor.clone()).map(move |service|{
if is_auth {
if let Ok(Some(Ok(key))) = service.keystore().contents()
.map(|keys| keys.get(0).map(|k| service.keystore().load(k, "")))
{
info!("Using authority key {}", key.public());
let task = start_aura(
AuraConfig {
local_key: Some(Arc::new(key)),
slot_duration: AURA_SLOT_DURATION,
},
service.client(),
service.proposer(),
service.network(),
);
executor.spawn(task);
}
}
service
})
}
},
LightService = Service<LightComponents<Self>> LightService = Service<LightComponents<Self>>
{ |config, executor| Service::<LightComponents<Factory>>::new(config, executor) }, { |config, executor| Service::<LightComponents<Factory>>::new(config, executor) },
ImportQueue = BasicQueue<Block, NoneVerifier> FullImportQueue = AuraImportQueue<Self::Block, FullClient<Self>>
{ |_, _| Ok(BasicQueue::new(Arc::new(NoneVerifier {}))) } { |config, client| Ok(import_queue(AuraConfig {
{ |_, _| Ok(BasicQueue::new(Arc::new(NoneVerifier {}))) }, local_key: None,
slot_duration: 5
}, client)) },
LightImportQueue = AuraImportQueue<Self::Block, LightClient<Self>>
{ |config, client| Ok(import_queue(AuraConfig {
local_key: None,
slot_duration: 5
}, client)) },
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#[cfg(feature = "rhd")] #[cfg(feature = "rhd")]
-24
View File
@@ -1,24 +0,0 @@
[package]
name = "node-consensus"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
error-chain = "0.12"
exit-future = "0.1"
futures = "0.1.17"
log = "0.4"
node-primitives = { path = "../primitives" }
node-runtime = { path = "../runtime" }
parity-codec = "2.1"
parking_lot = "0.4"
rhododendron = "0.3"
sr-primitives = { path = "../../core/sr-primitives" }
srml-system = { path = "../../srml/system" }
substrate-client = { path = "../../core/client" }
substrate-primitives = { path = "../../core/primitives" }
substrate-transaction-pool = { path = "../../core/transaction-pool" }
tokio = "0.1.7"
[dev-dependencies]
substrate-keyring = { path = "../../core/keyring" }
-5
View File
@@ -1,5 +0,0 @@
= Substrate Consensus
placeholder
//TODO Write content :)
-52
View File
@@ -1,52 +0,0 @@
// Copyright 2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate 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.
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Errors that can occur during the consensus process.
use primitives::AuthorityId;
use client;
error_chain! {
links {
Client(client::error::Error, client::error::ErrorKind);
Bft(::bft::Error, ::bft::ErrorKind);
}
errors {
NotValidator(id: AuthorityId) {
description("Local account ID not a validator at this block."),
display("Local account ID ({:?}) not a validator at this block.", id),
}
PrematureDestruction {
description("Proposer destroyed before finishing proposing or evaluating"),
display("Proposer destroyed before finishing proposing or evaluating"),
}
Timer(e: ::tokio::timer::Error) {
description("Failed to register or resolve async timer."),
display("Timer failed: {}", e),
}
Executor(e: ::futures::future::ExecuteErrorKind) {
description("Unable to dispatch agreement future"),
display("Unable to dispatch agreement future: {:?}", e),
}
}
}
impl From<::bft::InputStreamConcluded> for Error {
fn from(err: ::bft::InputStreamConcluded) -> Self {
::bft::Error::from(err).into()
}
}
-529
View File
@@ -1,529 +0,0 @@
// Copyright 2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate 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.
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
//! This service uses BFT consensus provided by the substrate.
#![cfg(feature="rhd")]
extern crate node_runtime;
extern crate node_primitives;
extern crate parity_codec as codec;
extern crate sr_primitives as runtime_primitives;
extern crate srml_system;
extern crate substrate_bft as bft;
extern crate substrate_client as client;
extern crate substrate_primitives as primitives;
extern crate substrate_transaction_pool as transaction_pool;
extern crate exit_future;
extern crate futures;
extern crate parking_lot;
extern crate rhododendron;
extern crate tokio;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate log;
#[cfg(test)]
extern crate substrate_keyring;
use std::sync::Arc;
use std::time::{self, Duration, Instant};
use client::{Client as SubstrateClient, CallExecutor};
use client::runtime_api::{Core, BlockBuilder as BlockBuilderAPI, Miscellaneous, OldTxQueue};
use codec::{Decode, Encode};
use node_primitives::{AccountId, Timestamp, SessionKey};
use node_runtime::{Runtime, InherentError, TimestampInherentError, InherentData};
use primitives::{AuthorityId, ed25519, Blake2Hasher};
use runtime_primitives::traits::{Block as BlockT, Hash as HashT, Header as HeaderT, As, BlockNumberToHash};
use runtime_primitives::generic::{BlockId, Era};
use srml_system::Trait as SystemT;
use transaction_pool::txpool::{self, Pool as TransactionPool};
use tokio::runtime::TaskExecutor;
use tokio::timer::Delay;
use futures::prelude::*;
use futures::future;
use parking_lot::RwLock;
pub use self::error::{ErrorKind, Error, Result};
pub use self::offline_tracker::OfflineTracker;
pub use service::Service;
mod evaluation;
mod error;
mod service;
/// Shared offline validator tracker.
pub type SharedOfflineTracker = Arc<RwLock<OfflineTracker>>;
// block size limit.
const MAX_TRANSACTIONS_SIZE: usize = 4 * 1024 * 1024;
/// Build new blocks.
pub trait BlockBuilder<Block: BlockT> {
/// Push an extrinsic onto the block. Fails if the extrinsic is invalid.
fn push_extrinsic(&mut self, extrinsic: <Block as BlockT>::Extrinsic) -> Result<()>;
}
/// Local client abstraction for the consensus.
pub trait AuthoringApi:
Send
+ Sync
+ BlockBuilderAPI<<Self as AuthoringApi>::Block, Error=<Self as AuthoringApi>::Error>
+ Core<<Self as AuthoringApi>::Block, AuthorityId, Error=<Self as AuthoringApi>::Error>
+ Miscellaneous<<Self as AuthoringApi>::Block, Error=<Self as AuthoringApi>::Error>
+ OldTxQueue<<Self as AuthoringApi>::Block, Error=<Self as AuthoringApi>::Error>
{
/// The block used for this API type.
type Block: BlockT;
/// The error used by this API type.
type Error: std::error::Error;
/// Build a block on top of the given, with inherent extrinsics pre-pushed.
fn build_block<F: FnMut(&mut BlockBuilder<Self::Block>) -> ()>(
&self,
at: &BlockId<Self::Block>,
inherent_data: InherentData,
build_ctx: F,
) -> Result<Self::Block>;
}
impl<'a, B, E, Block> BlockBuilder<Block> for client::block_builder::BlockBuilder<'a, B, E, Block, Blake2Hasher> where
B: client::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
Block: BlockT
{
fn push_extrinsic(&mut self, extrinsic: <Block as BlockT>::Extrinsic) -> Result<()> {
client::block_builder::BlockBuilder::push(self, extrinsic).map_err(Into::into)
}
}
impl<'a, B, E, Block> AuthoringApi for SubstrateClient<B, E, Block> where
B: client::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
Block: BlockT,
{
type Block = Block;
type Error = client::error::Error;
fn build_block<F: FnMut(&mut BlockBuilder<Self::Block>) -> ()>(
&self,
at: &BlockId<Self::Block>,
inherent_data: InherentData,
mut build_ctx: F,
) -> Result<Self::Block> {
let runtime_version = self.runtime_version_at(at)?;
let mut block_builder = self.new_block_at(at)?;
if runtime_version.has_api(*b"inherent", 1) {
self.inherent_extrinsics(at, &inherent_data)?
.into_iter().try_for_each(|i| block_builder.push(i))?;
}
build_ctx(&mut block_builder);
block_builder.bake().map_err(Into::into)
}
}
/// A long-lived network which can create BFT message routing processes on demand.
pub trait Network {
/// The block used for this API type.
type Block: BlockT;
/// The input stream of BFT messages. Should never logically conclude.
type Input: Stream<Item=bft::Communication<Self::Block>,Error=Error>;
/// The output sink of BFT messages. Messages sent here should eventually pass to all
/// current authorities.
type Output: Sink<SinkItem=bft::Communication<Self::Block>,SinkError=Error>;
/// Instantiate input and output streams.
fn communication_for(
&self,
validators: &[SessionKey],
local_id: SessionKey,
parent_hash: <Self::Block as BlockT>::Hash,
task_executor: TaskExecutor
) -> (Self::Input, Self::Output);
}
/// Proposer factory.
pub struct ProposerFactory<N, C, A> where
C: AuthoringApi,
A: txpool::ChainApi,
{
/// The client instance.
pub client: Arc<C>,
/// The transaction pool.
pub transaction_pool: Arc<TransactionPool<A>>,
/// The backing network handle.
pub network: N,
/// handle to remote task executor
pub handle: TaskExecutor,
/// Offline-tracker.
pub offline: SharedOfflineTracker,
/// Force delay in evaluation this long.
pub force_delay: Timestamp,
}
impl<N, C, A> bft::Environment<<C as AuthoringApi>::Block> for ProposerFactory<N, C, A> where
N: Network<Block=<C as AuthoringApi>::Block>,
C: AuthoringApi + BlockNumberToHash,
A: txpool::ChainApi<Block=<C as AuthoringApi>::Block>,
<<C as AuthoringApi>::Block as BlockT>::Hash:
Into<<Runtime as SystemT>::Hash> + PartialEq<primitives::H256> + Into<primitives::H256>,
Error: From<<C as AuthoringApi>::Error>
{
type Proposer = Proposer<C, A>;
type Input = N::Input;
type Output = N::Output;
type Error = Error;
fn init(
&self,
parent_header: &<<C as AuthoringApi>::Block as BlockT>::Header,
authorities: &[AuthorityId],
sign_with: Arc<ed25519::Pair>,
) -> Result<(Self::Proposer, Self::Input, Self::Output)> {
use runtime_primitives::traits::Hash as HashT;
let parent_hash = parent_header.hash();
let id = BlockId::hash(parent_hash);
let random_seed = self.client.random_seed(&id)?;
let random_seed = <<<C as AuthoringApi>::Block as BlockT>::Header as HeaderT>::Hashing::hash(random_seed.as_ref());
let validators = self.client.validators(&id)?;
self.offline.write().note_new_block(&validators[..]);
info!("Starting consensus session on top of parent {:?}", parent_hash);
let local_id = sign_with.public().0.into();
let (input, output) = self.network.communication_for(
authorities,
local_id,
parent_hash.clone(),
self.handle.clone(),
);
let now = Instant::now();
let proposer = Proposer {
client: self.client.clone(),
start: now,
local_key: sign_with,
parent_hash,
parent_id: id,
parent_number: *parent_header.number(),
random_seed,
transaction_pool: self.transaction_pool.clone(),
offline: self.offline.clone(),
validators,
minimum_timestamp: current_timestamp() + self.force_delay,
};
Ok((proposer, input, output))
}
}
/// The proposer logic.
pub struct Proposer<C: AuthoringApi, A: txpool::ChainApi> {
client: Arc<C>,
start: Instant,
local_key: Arc<ed25519::Pair>,
parent_hash: <<C as AuthoringApi>::Block as BlockT>::Hash,
parent_id: BlockId<<C as AuthoringApi>::Block>,
parent_number: <<<C as AuthoringApi>::Block as BlockT>::Header as HeaderT>::Number,
random_seed: <<C as AuthoringApi>::Block as BlockT>::Hash,
transaction_pool: Arc<TransactionPool<A>>,
offline: SharedOfflineTracker,
validators: Vec<AccountId>,
minimum_timestamp: u64,
}
impl<C: AuthoringApi, A: txpool::ChainApi> Proposer<C, A> {
fn primary_index(&self, round_number: usize, len: usize) -> usize {
use primitives::uint::U256;
let big_len = U256::from(len);
let offset = U256::from_big_endian(self.random_seed.as_ref()) % big_len;
let offset = offset.low_u64() as usize + round_number;
offset % len
}
}
impl<C, A> bft::Proposer<<C as AuthoringApi>::Block> for Proposer<C, A> where
C: AuthoringApi + BlockNumberToHash,
A: txpool::ChainApi<Block=<C as AuthoringApi>::Block>,
<<C as AuthoringApi>::Block as BlockT>::Hash:
Into<<Runtime as SystemT>::Hash> + PartialEq<primitives::H256> + Into<primitives::H256>,
error::Error: From<<C as AuthoringApi>::Error>
{
type Create = Result<<C as AuthoringApi>::Block>;
type Error = Error;
type Evaluate = Box<Future<Item=bool, Error=Error>>;
fn propose(&self) -> Result<<C as AuthoringApi>::Block> {
use runtime_primitives::traits::BlakeTwo256;
const MAX_VOTE_OFFLINE_SECONDS: Duration = Duration::from_secs(60);
// TODO: handle case when current timestamp behind that in state.
let timestamp = ::std::cmp::max(self.minimum_timestamp, current_timestamp());
let elapsed_since_start = self.start.elapsed();
let offline_indices = if elapsed_since_start > MAX_VOTE_OFFLINE_SECONDS {
Vec::new()
} else {
self.offline.read().reports(&self.validators[..])
};
if !offline_indices.is_empty() {
info!(
"Submitting offline validators {:?} for slash-vote",
offline_indices.iter().map(|&i| self.validators[i as usize]).collect::<Vec<_>>(),
)
}
let inherent_data = InherentData {
timestamp,
offline_indices,
};
let block = self.client.build_block(
&self.parent_id,
inherent_data,
|block_builder| {
let mut unqueue_invalid = Vec::new();
self.transaction_pool.ready(|pending_iterator| {
let mut pending_size = 0;
for pending in pending_iterator {
// TODO [ToDr] Probably get rid of it, and validate in runtime.
let encoded_size = pending.data.encode().len();
if pending_size + encoded_size >= MAX_TRANSACTIONS_SIZE { break }
match block_builder.push_extrinsic(pending.data.clone()) {
Ok(()) => {
pending_size += encoded_size;
}
Err(e) => {
trace!(target: "transaction-pool", "Invalid transaction: {}", e);
unqueue_invalid.push(pending.hash.clone());
}
}
}
});
self.transaction_pool.remove_invalid(&unqueue_invalid);
})?;
info!("Proposing block [number: {}; hash: {}; parent_hash: {}; extrinsics: [{}]]",
block.header().number(),
<<C as AuthoringApi>::Block as BlockT>::Hash::from(block.header().hash()),
block.header().parent_hash(),
block.extrinsics().iter()
.map(|xt| format!("{}", BlakeTwo256::hash_of(xt)))
.collect::<Vec<_>>()
.join(", ")
);
let substrate_block = Decode::decode(&mut block.encode().as_slice())
.expect("blocks are defined to serialize to substrate blocks correctly; qed");
assert!(evaluation::evaluate_initial(
&substrate_block,
&self.parent_hash,
self.parent_number,
).is_ok());
Ok(substrate_block)
}
fn evaluate(&self, unchecked_proposal: &<C as AuthoringApi>::Block) -> Self::Evaluate {
debug!(target: "bft", "evaluating block on top of parent ({}, {:?})", self.parent_number, self.parent_hash);
// do initial serialization and structural integrity checks.
match evaluation::evaluate_initial(
unchecked_proposal,
&self.parent_hash,
self.parent_number,
) {
Ok(p) => p,
Err(e) => {
// TODO: these errors are easily re-checked in runtime.
debug!(target: "bft", "Invalid proposal (initial evaluation failed): {:?}", e);
return Box::new(future::ok(false));
}
};
let current_timestamp = current_timestamp();
let inherent = InherentData::new(
current_timestamp,
self.offline.read().reports(&self.validators)
);
let proposed_timestamp = match self.client.check_inherents(
&self.parent_id,
&unchecked_proposal,
&inherent
) {
Ok(Ok(())) => None,
Ok(Err(InherentError::Timestamp(TimestampInherentError::TimestampInFuture(timestamp)))) => Some(timestamp),
Ok(Err(e)) => {
debug!(target: "bft", "Invalid proposal (check_inherents): {:?}", e);
return Box::new(future::ok(false));
},
Err(e) => {
debug!(target: "bft", "Could not call into runtime: {:?}", e);
return Box::new(future::ok(false));
}
};
let vote_delays = {
// the duration until the given timestamp is current
let proposed_timestamp = ::std::cmp::max(self.minimum_timestamp, proposed_timestamp.unwrap_or(0));
let timestamp_delay = if proposed_timestamp > current_timestamp {
let delay_s = proposed_timestamp - current_timestamp;
debug!(target: "bft", "Delaying evaluation of proposal for {} seconds", delay_s);
Some(Instant::now() + Duration::from_secs(delay_s))
} else {
None
};
match timestamp_delay {
Some(duration) => future::Either::A(
Delay::new(duration).map_err(|e| ErrorKind::Timer(e).into())
),
None => future::Either::B(future::ok(())),
}
};
// evaluate whether the block is actually valid.
// TODO: is it better to delay this until the delays are finished?
let evaluated = match self.client.execute_block(&self.parent_id, &unchecked_proposal.clone()).map_err(Error::from) {
Ok(()) => Ok(true),
Err(err) => match err.kind() {
error::ErrorKind::Client(client::error::ErrorKind::Execution(_)) => Ok(false),
_ => Err(err)
}
};
let future = future::result(evaluated).and_then(move |good| {
let end_result = future::ok(good);
if good {
// delay a "good" vote.
future::Either::A(vote_delays.and_then(|_| end_result))
} else {
// don't delay a "bad" evaluation.
future::Either::B(end_result)
}
});
Box::new(future) as Box<_>
}
fn round_proposer(&self, round_number: usize, authorities: &[AuthorityId]) -> AuthorityId {
let offset = self.primary_index(round_number, authorities.len());
let proposer = authorities[offset].clone();
trace!(target: "bft", "proposer for round {} is {}", round_number, proposer);
proposer
}
fn import_misbehavior(&self, misbehavior: Vec<(AuthorityId, bft::Misbehavior<<<C as AuthoringApi>::Block as BlockT>::Hash>)>) {
use rhododendron::Misbehavior as GenericMisbehavior;
use runtime_primitives::bft::{MisbehaviorKind, MisbehaviorReport};
use node_runtime::{Call, UncheckedExtrinsic, ConsensusCall};
let mut next_index = {
let local_id = self.local_key.public().0;
// let cur_index = self.transaction_pool.cull_and_get_pending(&BlockId::hash(self.parent_hash), |pending| pending
// .filter(|tx| tx.verified.sender == local_id)
// .last()
// .map(|tx| Ok(tx.verified.index()))
// .unwrap_or_else(|| self.client.account_nonce(&self.parent_id, local_id))
// .map_err(Error::from)
// );
// TODO [ToDr] Use pool data
let cur_index: Result<u64> = self.client.account_nonce(&self.parent_id, &local_id).map_err(Error::from);
match cur_index {
Ok(cur_index) => cur_index + 1,
Err(e) => {
warn!(target: "consensus", "Error computing next transaction index: {:?}", e);
return;
}
}
};
for (target, misbehavior) in misbehavior {
let report = MisbehaviorReport {
parent_hash: self.parent_hash.into(),
parent_number: self.parent_number.as_(),
target,
misbehavior: match misbehavior {
GenericMisbehavior::ProposeOutOfTurn(_, _, _) => continue,
GenericMisbehavior::DoublePropose(_, _, _) => continue,
GenericMisbehavior::DoublePrepare(round, (h1, s1), (h2, s2))
=> MisbehaviorKind::BftDoublePrepare(round as u32, (h1.into(), s1.signature), (h2.into(), s2.signature)),
GenericMisbehavior::DoubleCommit(round, (h1, s1), (h2, s2))
=> MisbehaviorKind::BftDoubleCommit(round as u32, (h1.into(), s1.signature), (h2.into(), s2.signature)),
}
};
let payload = (next_index, Call::Consensus(ConsensusCall::report_misbehavior(report)), Era::immortal(), self.client.genesis_hash());
let signature = self.local_key.sign(&payload.encode()).into();
next_index += 1;
let local_id = self.local_key.public().0.into();
let extrinsic = UncheckedExtrinsic {
signature: Some((node_runtime::RawAddress::Id(local_id), signature, payload.0, Era::immortal())),
function: payload.1,
};
let uxt: <<C as AuthoringApi>::Block as BlockT>::Extrinsic = Decode::decode(&mut extrinsic.encode().as_slice()).expect("Encoded extrinsic is valid");
let hash = BlockId::<<C as AuthoringApi>::Block>::hash(self.parent_hash);
if let Err(e) = self.transaction_pool.submit_one(&hash, uxt) {
warn!("Error importing misbehavior report: {:?}", e);
}
}
}
fn on_round_end(&self, round_number: usize, was_proposed: bool) {
let primary_validator = self.validators[
self.primary_index(round_number, self.validators.len())
];
// alter the message based on whether we think the empty proposer was forced to skip the round.
// this is determined by checking if our local validator would have been forced to skip the round.
if !was_proposed {
let public = ed25519::Public::from_raw(primary_validator.0);
info!(
"Potential Offline Validator: {} failed to propose during assigned slot: {}",
public,
round_number,
);
}
self.offline.write().note_round_end(primary_validator, was_proposed);
}
}
fn current_timestamp() -> Timestamp {
time::SystemTime::now().duration_since(time::UNIX_EPOCH)
.expect("now always later than unix epoch; qed")
.as_secs()
}
+6 -5
View File
@@ -254,6 +254,7 @@ mod tests {
timestamp: Some(Default::default()), timestamp: Some(Default::default()),
treasury: Some(Default::default()), treasury: Some(Default::default()),
contract: Some(Default::default()), contract: Some(Default::default()),
upgrade_key: Some(Default::default()),
}.build_storage().unwrap()) }.build_storage().unwrap())
} }
@@ -291,9 +292,9 @@ mod tests {
1, 1,
GENESIS_HASH.into(), GENESIS_HASH.into(),
if support_changes_trie { if support_changes_trie {
hex!("ffa85ed1832eae3e25e684d4f993ff0b5e8b6ac4d7ba0f40a5fb0114fda22f3d").into() hex!("978a3ff733a86638da39d36a349c693b5cf562bcc8db30fec6c2b6c40f925a9b").into()
} else { } else {
hex!("98971908b8923d07944cdf7ee658c203d17042ef447169adbdfec8160cfabcad").into() hex!("7bbad534e3de3db3c8cda015c4e8ed8ba10dde7e3fca21f4fd4fbc686e6c1410").into()
}, },
if support_changes_trie { if support_changes_trie {
Some(hex!("1f8f44dcae8982350c14dee720d34b147e73279f5a2ce1f9781195a991970978").into()) Some(hex!("1f8f44dcae8982350c14dee720d34b147e73279f5a2ce1f9781195a991970978").into())
@@ -317,7 +318,7 @@ mod tests {
construct_block( construct_block(
2, 2,
block1(false).1, block1(false).1,
hex!("788a2e8b23e4b30e1bce347ca6415fd0080e989d40741c86995b9ad539bb76b3").into(), hex!("7be30152ee2ee909047cffad5f0a28bf8c2b0a97c124b500aeac112f6917738e").into(),
None, None,
vec![ vec![
CheckedExtrinsic { CheckedExtrinsic {
@@ -340,7 +341,7 @@ mod tests {
construct_block( construct_block(
1, 1,
GENESIS_HASH.into(), GENESIS_HASH.into(),
hex!("acc03af5b3972deaf9dde4dfd99c5614a5360454313681b6fc299d1644ae8a59").into(), hex!("325a73726dc640af41becb42938e7152e218f130219c0695aae35b6a156f93f3").into(),
None, None,
vec![ vec![
CheckedExtrinsic { CheckedExtrinsic {
@@ -622,7 +623,7 @@ mod tests {
let b = construct_block( let b = construct_block(
1, 1,
GENESIS_HASH.into(), GENESIS_HASH.into(),
hex!("21fb6fb965f012ae3c6e521b71b5b57d6df17c738c52f202ec2809ca235eb082").into(), hex!("d68586d5098535e04ff7a12d71a9c9dc719960f318862e636e78a8e98cf4b8d4").into(),
None, None,
vec![ vec![
CheckedExtrinsic { CheckedExtrinsic {
-16
View File
@@ -1,16 +0,0 @@
[package]
name = "node-network"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
description = "Substrate node networking protocol"
[dependencies]
node-consensus = { path = "../consensus" }
node-primitives = { path = "../primitives" }
substrate-consensus-rhd = { path = "../../core/consensus/rhd" }
substrate-network = { path = "../../core/network" }
substrate-primitives = { path = "../../core/primitives" }
futures = "0.1"
tokio = "0.1.7"
log = "0.4"
rhododendron = "0.3"
-293
View File
@@ -1,293 +0,0 @@
// Copyright 2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate 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.
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
//! The "consensus" networking code built on top of the base network service.
//! This fulfills the `node_consensus::Network` trait, providing a hook to be called
//! each time consensus begins on a new chain head.
use bft;
use substrate_primitives::ed25519;
use substrate_network::{self as net, generic_message as msg};
use substrate_network::consensus_gossip::ConsensusMessage;
use node_consensus::{AuthoringApi, Network};
use node_primitives::{Block, Hash, SessionKey};
use rhododendron;
use futures::prelude::*;
use futures::sync::mpsc;
use std::sync::Arc;
use tokio::runtime::TaskExecutor;
use tokio::executor::Executor;
use super::NetworkService;
/// Sink for output BFT messages.
pub struct BftSink<E> {
network: Arc<NetworkService>,
parent_hash: Hash,
_marker: ::std::marker::PhantomData<E>,
}
impl<E> Sink for BftSink<E> {
type SinkItem = bft::Communication<Block>;
// TODO: replace this with the ! type when that's stabilized
type SinkError = E;
fn start_send(&mut self, message: bft::Communication<Block>)
-> ::futures::StartSend<bft::Communication<Block>, E>
{
let network_message = net::LocalizedBftMessage {
message: match message {
rhododendron::Communication::Consensus(c) => msg::BftMessage::Consensus(match c {
rhododendron::LocalizedMessage::Propose(proposal) => msg::SignedConsensusMessage::Propose(msg::SignedConsensusProposal {
round_number: proposal.round_number as u32,
proposal: proposal.proposal,
digest: proposal.digest,
sender: proposal.sender,
digest_signature: proposal.digest_signature.signature,
full_signature: proposal.full_signature.signature,
}),
rhododendron::LocalizedMessage::Vote(vote) => msg::SignedConsensusMessage::Vote(msg::SignedConsensusVote {
sender: vote.sender,
signature: vote.signature.signature,
vote: match vote.vote {
rhododendron::Vote::Prepare(r, h) => msg::ConsensusVote::Prepare(r as u32, h),
rhododendron::Vote::Commit(r, h) => msg::ConsensusVote::Commit(r as u32, h),
rhododendron::Vote::AdvanceRound(r) => msg::ConsensusVote::AdvanceRound(r as u32),
}
}),
}),
rhododendron::Communication::Auxiliary(justification) => {
let unchecked: bft::UncheckedJustification<_> = justification.uncheck().into();
msg::BftMessage::Auxiliary(unchecked.into())
}
},
parent_hash: self.parent_hash,
};
self.network.with_spec(
move |spec, ctx| spec.consensus_gossip.multicast_bft_message(ctx, network_message)
);
Ok(::futures::AsyncSink::Ready)
}
fn poll_complete(&mut self) -> ::futures::Poll<(), E> {
Ok(Async::Ready(()))
}
}
// check signature and authority validity of message.
fn process_bft_message(
msg: msg::LocalizedBftMessage<Block, Hash>,
local_id: &SessionKey,
authorities: &[SessionKey]
) -> Result<Option<bft::Communication<Block>>, bft::Error>
{
Ok(Some(match msg.message {
msg::BftMessage::Consensus(c) => rhododendron::Communication::Consensus(match c {
msg::SignedConsensusMessage::Propose(proposal) => rhododendron::LocalizedMessage::Propose({
if &proposal.sender == local_id { return Ok(None) }
let proposal = rhododendron::LocalizedProposal {
round_number: proposal.round_number as usize,
proposal: proposal.proposal,
digest: proposal.digest,
sender: proposal.sender,
digest_signature: ed25519::LocalizedSignature {
signature: proposal.digest_signature,
signer: ed25519::Public(proposal.sender.into()),
},
full_signature: ed25519::LocalizedSignature {
signature: proposal.full_signature,
signer: ed25519::Public(proposal.sender.into()),
}
};
bft::check_proposal(authorities, &msg.parent_hash, &proposal)?;
trace!(target: "bft", "importing proposal message for round {} from {}", proposal.round_number, Hash::from(proposal.sender.0));
proposal
}),
msg::SignedConsensusMessage::Vote(vote) => rhododendron::LocalizedMessage::Vote({
if &vote.sender == local_id { return Ok(None) }
let vote = rhododendron::LocalizedVote {
sender: vote.sender,
signature: ed25519::LocalizedSignature {
signature: vote.signature,
signer: ed25519::Public(vote.sender.0),
},
vote: match vote.vote {
msg::ConsensusVote::Prepare(r, h) => rhododendron::Vote::Prepare(r as usize, h),
msg::ConsensusVote::Commit(r, h) => rhododendron::Vote::Commit(r as usize, h),
msg::ConsensusVote::AdvanceRound(r) => rhododendron::Vote::AdvanceRound(r as usize),
}
};
bft::check_vote::<Block>(authorities, &msg.parent_hash, &vote)?;
trace!(target: "bft", "importing vote {:?} from {}", vote.vote, Hash::from(vote.sender.0));
vote
}),
}),
msg::BftMessage::Auxiliary(a) => {
let justification = bft::UncheckedJustification::from(a);
// TODO: get proper error
let justification: Result<_, bft::Error> = bft::check_prepare_justification::<Block>(authorities, msg.parent_hash, justification)
.map_err(|_| bft::ErrorKind::InvalidJustification.into());
rhododendron::Communication::Auxiliary(justification?)
},
}))
}
// task that processes all gossipped consensus messages,
// checking signatures
struct MessageProcessTask {
inner_stream: mpsc::UnboundedReceiver<ConsensusMessage<Block>>,
bft_messages: mpsc::UnboundedSender<bft::Communication<Block>>,
validators: Vec<SessionKey>,
local_id: SessionKey,
}
impl MessageProcessTask {
fn process_message(&self, msg: ConsensusMessage<Block>) -> Option<Async<()>> {
match msg {
ConsensusMessage::Bft(msg) => {
match process_bft_message(msg, &self.local_id, &self.validators[..]) {
Ok(Some(msg)) => {
if let Err(_) = self.bft_messages.unbounded_send(msg) {
// if the BFT receiving stream has ended then
// we should just bail.
trace!(target: "bft", "BFT message stream appears to have closed");
return Some(Async::Ready(()));
}
}
Ok(None) => {} // ignored local message
Err(e) => {
debug!("Message validation failed: {:?}", e);
}
}
}
ConsensusMessage::ChainSpecific(_, _) => {
panic!("ChainSpecific messages are not allowed by the top level message handler");
}
}
None
}
}
impl Future for MessageProcessTask {
type Item = ();
type Error = ();
fn poll(&mut self) -> Poll<(), ()> {
loop {
match self.inner_stream.poll() {
Ok(Async::Ready(Some(val))) => if let Some(async) = self.process_message(val) {
return Ok(async);
},
Ok(Async::Ready(None)) => return Ok(Async::Ready(())),
Ok(Async::NotReady) => return Ok(Async::NotReady),
Err(e) => {
debug!(target: "node-network", "Error getting consensus message: {:?}", e);
return Err(e);
},
}
}
}
}
/// Input stream from the consensus network.
pub struct InputAdapter {
input: mpsc::UnboundedReceiver<bft::Communication<Block>>,
}
impl Stream for InputAdapter {
type Item = bft::Communication<Block>;
type Error = ::node_consensus::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
match self.input.poll() {
Err(_) | Ok(Async::Ready(None)) => Err(bft::InputStreamConcluded.into()),
Ok(x) => Ok(x)
}
}
}
/// Wrapper around the network service
pub struct ConsensusNetwork<P> {
network: Arc<NetworkService>,
api: Arc<P>,
}
impl<P> ConsensusNetwork<P> {
/// Create a new consensus networking object.
pub fn new(network: Arc<NetworkService>, api: Arc<P>) -> Self {
ConsensusNetwork { network, api }
}
}
impl<P> Clone for ConsensusNetwork<P> {
fn clone(&self) -> Self {
ConsensusNetwork {
network: self.network.clone(),
api: self.api.clone(),
}
}
}
/// A long-lived network which can create parachain statement and BFT message routing processes on demand.
impl<P: AuthoringApi + Send + Sync + 'static> Network for ConsensusNetwork<P> {
/// The input stream of BFT messages. Should never logically conclude.
type Input = InputAdapter;
/// The output sink of BFT messages. Messages sent here should eventually pass to all
/// current validators.
type Output = BftSink<::node_consensus::Error>;
type Block = Block;
/// Get input and output streams of BFT messages.
fn communication_for(
&self, validators: &[SessionKey],
local_id: SessionKey,
parent_hash: Hash,
mut task_executor: TaskExecutor
) -> (Self::Input, Self::Output)
{
let sink = BftSink {
network: self.network.clone(),
parent_hash,
_marker: Default::default(),
};
let (bft_send, bft_recv) = mpsc::unbounded();
// spin up a task in the background that processes all incoming statements
// TODO: propagate statements on a timer?
let process_task = self.network.with_spec(|spec, _ctx| {
spec.consensus_gossip.new_session(parent_hash);
MessageProcessTask {
inner_stream: spec.consensus_gossip.messages_for(parent_hash),
bft_messages: bft_send,
validators: validators.to_vec(),
local_id,
}
});
if let Err(e) = Executor::spawn(&mut task_executor, Box::new(process_task)) {
debug!(target: "node-network", "Cannot spawn message processing: {:?}", e)
}
(InputAdapter { input: bft_recv }, sink)
}
}
-38
View File
@@ -1,38 +0,0 @@
// Copyright 2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate 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.
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Substrate-specific network implementation.
//!
//! This manages gossip of consensus messages for BFT.
#![warn(unused_extern_crates)]
#[macro_use]
extern crate substrate_network;
extern crate node_primitives;
use node_primitives::{Block, Hash};
use substrate_network::consensus_gossip::ConsensusGossip;
/// Specialization of the network service for the node protocol.
pub type NetworkService = ::substrate_network::Service<Block, Protocol, Hash>;
construct_simple_protocol! {
/// Demo protocol attachment for substrate.
pub struct Protocol where Block = Block {
consensus_gossip: ConsensusGossip<Block>,
}
}
+2
View File
@@ -29,6 +29,7 @@ srml-staking = { path = "../../srml/staking" }
srml-system = { path = "../../srml/system" } srml-system = { path = "../../srml/system" }
srml-timestamp = { path = "../../srml/timestamp" } srml-timestamp = { path = "../../srml/timestamp" }
srml-treasury = { path = "../../srml/treasury" } srml-treasury = { path = "../../srml/treasury" }
srml-upgrade-key = { path = "../../srml/upgrade-key" }
sr-version = { path = "../../core/sr-version" } sr-version = { path = "../../core/sr-version" }
node-primitives = { path = "../primitives" } node-primitives = { path = "../primitives" }
@@ -53,6 +54,7 @@ std = [
"srml-system/std", "srml-system/std",
"srml-timestamp/std", "srml-timestamp/std",
"srml-treasury/std", "srml-treasury/std",
"srml-upgrade-key/std",
"sr-version/std", "sr-version/std",
"node-primitives/std", "node-primitives/std",
"serde_derive", "serde_derive",
+17 -34
View File
@@ -52,6 +52,7 @@ extern crate srml_staking as staking;
extern crate srml_system as system; extern crate srml_system as system;
extern crate srml_timestamp as timestamp; extern crate srml_timestamp as timestamp;
extern crate srml_treasury as treasury; extern crate srml_treasury as treasury;
extern crate srml_upgrade_key as upgrade_key;
#[macro_use] #[macro_use]
extern crate sr_version as version; extern crate sr_version as version;
extern crate node_primitives; extern crate node_primitives;
@@ -62,12 +63,12 @@ use node_primitives::{
AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, AccountId, AccountIndex, Balance, BlockNumber, Hash, Index,
SessionKey, Signature SessionKey, Signature
}; };
use runtime_api::runtime::*; use runtime_api::{runtime::*, id::*};
use runtime_primitives::ApplyResult; use runtime_primitives::ApplyResult;
use runtime_primitives::transaction_validity::TransactionValidity; use runtime_primitives::transaction_validity::TransactionValidity;
use runtime_primitives::generic; use runtime_primitives::generic;
use runtime_primitives::traits::{Convert, BlakeTwo256, Block as BlockT}; use runtime_primitives::traits::{Convert, BlakeTwo256, Block as BlockT};
use version::{RuntimeVersion, ApiId}; use version::RuntimeVersion;
use council::{motions as council_motions, voting as council_voting}; use council::{motions as council_motions, voting as council_voting};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use council::seats as council_seats; use council::seats as council_seats;
@@ -81,14 +82,11 @@ pub use timestamp::Call as TimestampCall;
pub use balances::Call as BalancesCall; pub use balances::Call as BalancesCall;
pub use runtime_primitives::{Permill, Perbill}; pub use runtime_primitives::{Permill, Perbill};
pub use timestamp::BlockPeriod; pub use timestamp::BlockPeriod;
pub use srml_support::StorageValue; pub use srml_support::{StorageValue, RuntimeMetadata};
const TIMESTAMP_SET_POSITION: u32 = 0; const TIMESTAMP_SET_POSITION: u32 = 0;
const NOTE_OFFLINE_POSITION: u32 = 1; const NOTE_OFFLINE_POSITION: u32 = 1;
const INHERENT: ApiId = *b"inherent";
const VALIDATX: ApiId = *b"validatx";
/// Runtime version. /// Runtime version.
pub const VERSION: RuntimeVersion = RuntimeVersion { pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: ver_str!("node"), spec_name: ver_str!("node"),
@@ -96,7 +94,11 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
authoring_version: 1, authoring_version: 1,
spec_version: 1, spec_version: 1,
impl_version: 0, impl_version: 0,
apis: apis_vec!([(INHERENT, 1), (VALIDATX, 1)]), apis: apis_vec!([
(BLOCK_BUILDER, 1),
(TAGGED_TRANSACTION_QUEUE, 1),
(METADATA, 1)
]),
}; };
/// Native version. /// Native version.
@@ -191,15 +193,19 @@ impl contract::Trait for Runtime {
type Event = Event; type Event = Event;
} }
impl upgrade_key::Trait for Runtime {
type Event = Event;
}
construct_runtime!( construct_runtime!(
pub enum Runtime with Log(InternalLog: DigestItem<Hash, SessionKey>) where pub enum Runtime with Log(InternalLog: DigestItem<Hash, SessionKey>) where
Block = Block, Block = Block,
UncheckedExtrinsic = UncheckedExtrinsic UncheckedExtrinsic = UncheckedExtrinsic
{ {
System: system::{default, Log(ChangesTrieRoot)}, System: system::{default, Log(ChangesTrieRoot)},
Timestamp: timestamp::{Module, Call, Storage, Config<T>, Inherent},
Consensus: consensus::{Module, Call, Storage, Config<T>, Log(AuthoritiesChange), Inherent}, Consensus: consensus::{Module, Call, Storage, Config<T>, Log(AuthoritiesChange), Inherent},
Balances: balances, Balances: balances,
Timestamp: timestamp::{Module, Call, Storage, Config<T>, Inherent},
Session: session, Session: session,
Staking: staking, Staking: staking,
Democracy: democracy, Democracy: democracy,
@@ -209,6 +215,7 @@ construct_runtime!(
CouncilSeats: council_seats::{Config<T>}, CouncilSeats: council_seats::{Config<T>},
Treasury: treasury, Treasury: treasury,
Contract: contract::{Module, Call, Config<T>, Event<T>}, Contract: contract::{Module, Call, Config<T>, Event<T>},
UpgradeKey: upgrade_key,
} }
); );
@@ -246,8 +253,8 @@ impl_apis! {
} }
} }
impl Metadata for Runtime { impl Metadata<RuntimeMetadata> for Runtime {
fn metadata() -> Vec<u8> { fn metadata() -> RuntimeMetadata {
Runtime::metadata() Runtime::metadata()
} }
} }
@@ -278,33 +285,9 @@ impl_apis! {
} }
} }
impl OldTxQueue<AccountId, Index, Address, AccountId> for Runtime {
fn account_nonce(account: AccountId) -> Index {
System::account_nonce(&account)
}
fn lookup_address(address: Address) -> Option<AccountId> {
Balances::lookup_address(address)
}
}
impl TaggedTransactionQueue<Block, TransactionValidity> for Runtime { impl TaggedTransactionQueue<Block, TransactionValidity> for Runtime {
fn validate_transaction(tx: <Block as BlockT>::Extrinsic) -> TransactionValidity { fn validate_transaction(tx: <Block as BlockT>::Extrinsic) -> TransactionValidity {
Executive::validate_transaction(tx) Executive::validate_transaction(tx)
} }
} }
impl Miscellaneous<AccountId, u64> for Runtime {
fn validator_count() -> u32 {
Session::validator_count()
}
fn validators() -> Vec<AccountId> {
Session::validators()
}
fn timestamp() -> u64 {
Timestamp::get()
}
}
} }
+19
View File
@@ -285,6 +285,7 @@ dependencies = [
"srml-system 0.1.0", "srml-system 0.1.0",
"srml-timestamp 0.1.0", "srml-timestamp 0.1.0",
"srml-treasury 0.1.0", "srml-treasury 0.1.0",
"srml-upgrade-key 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
] ]
@@ -817,6 +818,24 @@ dependencies = [
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
] ]
[[package]]
name = "srml-upgrade-key"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 0.1.0",
"sr-primitives 0.1.0",
"sr-std 0.1.0",
"srml-consensus 0.1.0",
"srml-support 0.1.0",
"srml-system 0.1.0",
"substrate-primitives 0.1.0",
]
[[package]] [[package]]
name = "stable_deref_trait" name = "stable_deref_trait"
version = "1.1.1" version = "1.1.1"
+2
View File
@@ -28,6 +28,7 @@ srml-staking = { path = "../../../srml/staking", default-features = false }
srml-system = { path = "../../../srml/system", default-features = false } srml-system = { path = "../../../srml/system", default-features = false }
srml-timestamp = { path = "../../../srml/timestamp", default-features = false } srml-timestamp = { path = "../../../srml/timestamp", default-features = false }
srml-treasury = { path = "../../../srml/treasury", default-features = false } srml-treasury = { path = "../../../srml/treasury", default-features = false }
srml-upgrade-key = { path = "../../../srml/upgrade-key", default-features = false }
sr-version = { path = "../../../core/sr-version", default-features = false } sr-version = { path = "../../../core/sr-version", default-features = false }
node-primitives = { path = "../../primitives", default-features = false } node-primitives = { path = "../../primitives", default-features = false }
@@ -53,6 +54,7 @@ std = [
"srml-system/std", "srml-system/std",
"srml-timestamp/std", "srml-timestamp/std",
"srml-treasury/std", "srml-treasury/std",
"srml-upgrade-key/std",
"sr-version/std", "sr-version/std",
"node-primitives/std", "node-primitives/std",
] ]
+34 -52
View File
@@ -52,7 +52,6 @@ extern crate sr_primitives as primitives;
// depend on it being around. // depend on it being around.
extern crate srml_system as system; extern crate srml_system as system;
use primitives::traits::OnFinalise;
use runtime_support::{StorageValue, StorageMap, dispatch::Result, Parameter}; use runtime_support::{StorageValue, StorageMap, dispatch::Result, Parameter};
use primitives::traits::{Member, SimpleArithmetic, Zero}; use primitives::traits::{Member, SimpleArithmetic, Zero};
use system::ensure_signed; use system::ensure_signed;
@@ -70,16 +69,47 @@ type AssetId = u32;
decl_module! { decl_module! {
// Simple declaration of the `Module` type. Lets the macro know what its working on. // Simple declaration of the `Module` type. Lets the macro know what its working on.
pub struct Module<T: Trait> for enum Call where origin: T::Origin { pub struct Module<T: Trait> for enum Call where origin: T::Origin {
fn deposit_event() = default;
/// Issue a new class of fungible assets. There are, and will only ever be, `total` /// Issue a new class of fungible assets. There are, and will only ever be, `total`
/// such assets and they'll all belong to the `origin` initially. It will have an /// such assets and they'll all belong to the `origin` initially. It will have an
/// identifier `AssetId` instance: this will be specified in the `Issued` event. /// identifier `AssetId` instance: this will be specified in the `Issued` event.
fn issue(origin, total: T::Balance) -> Result; fn issue(origin, total: T::Balance) -> Result {
let origin = ensure_signed(origin)?;
let id = Self::next_asset_id();
<NextAssetId<T>>::mutate(|id| *id += 1);
<Balances<T>>::insert((id, origin.clone()), total);
Self::deposit_event(RawEvent::Issued(id, origin, total));
Ok(())
}
/// Move some assets from one holder to another. /// Move some assets from one holder to another.
fn transfer(origin, id: AssetId, target: T::AccountId, total: T::Balance) -> Result; fn transfer(origin, id: AssetId, target: T::AccountId, amount: T::Balance) -> Result {
let origin = ensure_signed(origin)?;
let origin_account = (id, origin.clone());
let origin_balance = <Balances<T>>::get(&origin_account);
ensure!(origin_balance >= amount, "origin account balance must be greater than amount");
Self::deposit_event(RawEvent::Transfered(id, origin, target.clone(), amount));
<Balances<T>>::insert(origin_account, origin_balance - amount);
<Balances<T>>::mutate((id, target), |balance| *balance += amount);
Ok(())
}
/// Destroy any assets of `id` owned by `origin`. /// Destroy any assets of `id` owned by `origin`.
fn destroy(origin, id: AssetId) -> Result; fn destroy(origin, id: AssetId) -> Result {
let origin = ensure_signed(origin)?;
let balance = <Balances<T>>::take((id, origin.clone()));
ensure!(!balance.is_zero(), "origin balance should be non-zero");
Self::deposit_event(RawEvent::Destroyed(id, origin, balance));
Ok(())
}
} }
} }
@@ -108,62 +138,14 @@ decl_storage! {
// The main implementation block for the module. // The main implementation block for the module.
impl<T: Trait> Module<T> { impl<T: Trait> Module<T> {
/// Deposit one of this module's events.
// TODO: move into `decl_module` macro.
fn deposit_event(event: Event<T>) {
<system::Module<T>>::deposit_event(<T as Trait>::Event::from(event).into());
}
// Public immutables // Public immutables
/// Get the asset `id` balance of `who`. /// Get the asset `id` balance of `who`.
pub fn balance(id: AssetId, who: T::AccountId) -> T::Balance { pub fn balance(id: AssetId, who: T::AccountId) -> T::Balance {
<Balances<T>>::get((id, who)) <Balances<T>>::get((id, who))
} }
// Implement Calls and add public immutables and private mutables.
fn issue(origin: T::Origin, total: T::Balance) -> Result {
let origin = ensure_signed(origin)?;
let id = Self::next_asset_id();
<NextAssetId<T>>::mutate(|id| *id += 1);
<Balances<T>>::insert((id, origin.clone()), total);
Self::deposit_event(RawEvent::Issued(id, origin, total));
Ok(())
} }
fn transfer(origin: T::Origin, id: AssetId, target: T::AccountId, amount: T::Balance) -> Result {
let origin = ensure_signed(origin)?;
let origin_account = (id, origin.clone());
let origin_balance = <Balances<T>>::get(&origin_account);
ensure!(origin_balance >= amount, "origin account balance must be greater than amount");
Self::deposit_event(RawEvent::Transfered(id, origin, target.clone(), amount));
<Balances<T>>::insert(origin_account, origin_balance - amount);
<Balances<T>>::mutate((id, target), |balance| *balance += amount);
Ok(())
}
fn destroy(origin: T::Origin, id: AssetId) -> Result {
let origin = ensure_signed(origin)?;
let balance = <Balances<T>>::take((id, origin.clone()));
ensure!(!balance.is_zero(), "origin balance should be non-zero");
Self::deposit_event(RawEvent::Destroyed(id, origin, balance));
Ok(())
}
}
// This trait expresses what should happen when the block is finalised.
impl<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
+76 -65
View File
@@ -44,7 +44,7 @@ use rstd::{cmp, result};
use codec::{Encode, Decode, Codec, Input, Output, HasCompact}; use codec::{Encode, Decode, Codec, Input, Output, HasCompact};
use runtime_support::{StorageValue, StorageMap, Parameter}; use runtime_support::{StorageValue, StorageMap, Parameter};
use runtime_support::dispatch::Result; use runtime_support::dispatch::Result;
use primitives::traits::{Zero, One, SimpleArithmetic, OnFinalise, MakePayment, use primitives::traits::{Zero, One, SimpleArithmetic, MakePayment,
As, Lookup, Member, CheckedAdd, CheckedSub, CurrentHeight, BlockNumberToHash}; As, Lookup, Member, CheckedAdd, CheckedSub, CurrentHeight, BlockNumberToHash};
use address::Address as RawAddress; use address::Address as RawAddress;
use system::ensure_signed; use system::ensure_signed;
@@ -125,8 +125,64 @@ pub trait Trait: system::Trait {
decl_module! { decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin { pub struct Module<T: Trait> for enum Call where origin: T::Origin {
fn transfer(origin, dest: RawAddress<T::AccountId, T::AccountIndex>, value: <T::Balance as HasCompact>::Type) -> Result; fn deposit_event() = default;
fn set_balance(who: RawAddress<T::AccountId, T::AccountIndex>, free: <T::Balance as HasCompact>::Type, reserved: <T::Balance as HasCompact>::Type) -> Result;
/// Transfer some liquid free balance to another staker.
pub fn transfer(
origin,
dest: RawAddress<T::AccountId, T::AccountIndex>,
value: <T::Balance as HasCompact>::Type
) -> Result {
let transactor = ensure_signed(origin)?;
let dest = Self::lookup(dest)?;
let value = value.into();
let from_balance = Self::free_balance(&transactor);
let to_balance = Self::free_balance(&dest);
let would_create = to_balance.is_zero();
let fee = if would_create { Self::creation_fee() } else { Self::transfer_fee() };
let liability = match value.checked_add(&fee) {
Some(l) => l,
None => return Err("got overflow after adding a fee to value"),
};
let new_from_balance = match from_balance.checked_sub(&liability) {
Some(b) => b,
None => return Err("balance too low to send value"),
};
if would_create && value < Self::existential_deposit() {
return Err("value too low to create account");
}
T::EnsureAccountLiquid::ensure_account_liquid(&transactor)?;
// NOTE: total stake being stored in the same type means that this could never overflow
// but better to be safe than sorry.
let new_to_balance = match to_balance.checked_add(&value) {
Some(b) => b,
None => return Err("destination balance too high to receive value"),
};
if transactor != dest {
Self::set_free_balance(&transactor, new_from_balance);
Self::decrease_total_stake_by(fee);
Self::set_free_balance_creating(&dest, new_to_balance);
Self::deposit_event(RawEvent::Transfer(transactor, dest, value, fee));
}
Ok(())
}
/// Set the balances of a given account.
fn set_balance(
who: RawAddress<T::AccountId, T::AccountIndex>,
free: <T::Balance as HasCompact>::Type,
reserved: <T::Balance as HasCompact>::Type
) -> Result {
let who = Self::lookup(who)?;
Self::set_free_balance(&who, free.into());
Self::set_reserved_balance(&who, reserved.into());
Ok(())
}
} }
} }
@@ -232,12 +288,6 @@ pub enum UpdateBalanceOutcome {
} }
impl<T: Trait> Module<T> { impl<T: Trait> Module<T> {
/// Deposit one of this module's events.
fn deposit_event(event: Event<T>) {
<system::Module<T>>::deposit_event(<T as Trait>::Event::from(event).into());
}
// PUBLIC IMMUTABLES // PUBLIC IMMUTABLES
/// The combined balance of `who`. /// The combined balance of `who`.
@@ -285,57 +335,6 @@ impl<T: Trait> Module<T> {
} }
} }
// PUBLIC DISPATCH
/// Transfer some liquid free balance to another staker.
pub fn transfer(origin: T::Origin, dest: Address<T>, value: <T::Balance as HasCompact>::Type) -> Result {
let transactor = ensure_signed(origin)?;
let dest = Self::lookup(dest)?;
let value = value.into();
let from_balance = Self::free_balance(&transactor);
let to_balance = Self::free_balance(&dest);
let would_create = to_balance.is_zero();
let fee = if would_create { Self::creation_fee() } else { Self::transfer_fee() };
let liability = match value.checked_add(&fee) {
Some(l) => l,
None => return Err("got overflow after adding a fee to value"),
};
let new_from_balance = match from_balance.checked_sub(&liability) {
Some(b) => b,
None => return Err("balance too low to send value"),
};
if would_create && value < Self::existential_deposit() {
return Err("value too low to create account");
}
T::EnsureAccountLiquid::ensure_account_liquid(&transactor)?;
// NOTE: total stake being stored in the same type means that this could never overflow
// but better to be safe than sorry.
let new_to_balance = match to_balance.checked_add(&value) {
Some(b) => b,
None => return Err("destination balance too high to receive value"),
};
if transactor != dest {
Self::set_free_balance(&transactor, new_from_balance);
Self::decrease_total_stake_by(fee);
Self::set_free_balance_creating(&dest, new_to_balance);
Self::deposit_event(RawEvent::Transfer(transactor, dest, value, fee));
}
Ok(())
}
/// Set the balances of a given account.
fn set_balance(who: Address<T>, free: <T::Balance as HasCompact>::Type, reserved: <T::Balance as HasCompact>::Type) -> Result {
let who = Self::lookup(who)?;
Self::set_free_balance(&who, free.into());
Self::set_reserved_balance(&who, reserved.into());
Ok(())
}
//PUBLIC MUTABLES (DANGEROUS) //PUBLIC MUTABLES (DANGEROUS)
/// Set the free balance of an account to some new value. /// Set the free balance of an account to some new value.
@@ -424,6 +423,23 @@ impl<T: Trait> Module<T> {
Self::set_free_balance_creating(who, Self::free_balance(who) + value) Self::set_free_balance_creating(who, Self::free_balance(who) + value)
} }
/// Substrates `value` from the free balance of `who`. If the whole amount cannot be
/// deducted, an error is returned.
///
/// NOTE: This assumes that the total stake remains unchanged after this operation. If
/// you mean to actually burn value out of existence, then use `slash` instead.
pub fn decrease_free_balance(
who: &T::AccountId,
value: T::Balance
) -> result::Result<UpdateBalanceOutcome, &'static str> {
T::EnsureAccountLiquid::ensure_account_liquid(who)?;
let b = Self::free_balance(who);
if b < value {
return Err("account has too few funds")
}
Ok(Self::set_free_balance(who, b - value))
}
/// Deducts up to `value` from the combined balance of `who`, preferring to deduct from the /// Deducts up to `value` from the combined balance of `who`, preferring to deduct from the
/// free balance. This function cannot fail. /// free balance. This function cannot fail.
/// ///
@@ -652,11 +668,6 @@ impl<T: Trait> Module<T> {
} }
} }
impl<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
fn on_finalise(_n: T::BlockNumber) {
}
}
pub struct ChainContext<T>(::rstd::marker::PhantomData<T>); pub struct ChainContext<T>(::rstd::marker::PhantomData<T>);
impl<T> Default for ChainContext<T> { impl<T> Default for ChainContext<T> {
fn default() -> Self { fn default() -> Self {

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