mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-21 13:15:41 +00:00
Initial GRANDPA integration (#866)
* implement grandpa client * consensus gossip with arbitrary topics * defer GRANDPA messages until referenced blocks imported * set up communication for voter in a transparent way * instantiate GRANDPA voter * keep last round state on disk * switch back to crates.io finality-grandpa * update cargo.lock * use new `collect_garbage` API * update sync test framework and make public * test that observers can observe * fix warning * use more idiomatic predicate for collecting garbage in gossip * kill spaces * fix date
This commit is contained in:
committed by
Gav Wood
parent
1cc0e3b6ea
commit
68b4be14ff
Generated
+91
-61
@@ -42,7 +42,7 @@ name = "aio-limited"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/paritytech/aio-limited.git#1f42497dcd2a6f85b83af97cd80314b26a1e4a9e"
|
source = "git+https://github.com/paritytech/aio-limited.git#1f42497dcd2a6f85b83af97cd80314b26a1e4a9e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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.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)",
|
||||||
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -467,7 +467,7 @@ source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9
|
|||||||
dependencies = [
|
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.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -563,7 +563,7 @@ name = "exit-future"
|
|||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -600,6 +600,18 @@ dependencies = [
|
|||||||
"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)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "finality-grandpa"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"futures 0.1.24 (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.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fixed-hash"
|
name = "fixed-hash"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@@ -654,7 +666,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.1.21"
|
version = "0.1.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -662,7 +674,7 @@ name = "futures-cpupool"
|
|||||||
version = "0.1.8"
|
version = "0.1.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -787,7 +799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"base64 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"httparse 1.2.4 (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)",
|
||||||
@@ -869,7 +881,7 @@ name = "jsonrpc-core"
|
|||||||
version = "8.0.2"
|
version = "8.0.2"
|
||||||
source = "git+https://github.com/paritytech/jsonrpc.git#53f814e94317313ccb485eb57e435c921a974cf0"
|
source = "git+https://github.com/paritytech/jsonrpc.git#53f814e94317313ccb485eb57e435c921a974cf0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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.70 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -1031,7 +1043,7 @@ version = "0.1.0"
|
|||||||
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"libp2p-dns 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
|
"libp2p-dns 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
|
||||||
"libp2p-floodsub 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
|
"libp2p-floodsub 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
|
||||||
@@ -1063,7 +1075,7 @@ dependencies = [
|
|||||||
"bs58 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bs58 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"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)",
|
||||||
"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)",
|
||||||
@@ -1083,7 +1095,7 @@ name = "libp2p-dns"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"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)",
|
||||||
"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)",
|
||||||
@@ -1100,7 +1112,7 @@ dependencies = [
|
|||||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"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)",
|
||||||
"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)",
|
||||||
@@ -1119,7 +1131,7 @@ source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
|
"libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
|
||||||
"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)",
|
||||||
@@ -1142,7 +1154,7 @@ dependencies = [
|
|||||||
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"datastore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
|
"datastore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
|
||||||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"libp2p-identify 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
|
"libp2p-identify 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
|
||||||
"libp2p-ping 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
|
"libp2p-ping 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
|
||||||
@@ -1165,7 +1177,7 @@ source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"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.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -1181,7 +1193,7 @@ source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bs58 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bs58 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"datastore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
|
"datastore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"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)",
|
||||||
@@ -1195,7 +1207,7 @@ version = "0.1.0"
|
|||||||
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"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)",
|
||||||
"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)",
|
||||||
@@ -1212,7 +1224,7 @@ version = "0.1.1"
|
|||||||
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aio-limited 0.1.0 (git+https://github.com/paritytech/aio-limited.git)",
|
"aio-limited 0.1.0 (git+https://github.com/paritytech/aio-limited.git)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"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)",
|
||||||
"tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -1225,7 +1237,7 @@ version = "0.1.0"
|
|||||||
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
|
"libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
|
||||||
"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)",
|
||||||
@@ -1247,7 +1259,7 @@ dependencies = [
|
|||||||
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (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.0 (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.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"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)",
|
||||||
"protobuf 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"protobuf 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -1264,7 +1276,7 @@ name = "libp2p-tcp-transport"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"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)",
|
||||||
"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)",
|
||||||
@@ -1278,7 +1290,7 @@ name = "libp2p-transport-timeout"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"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)",
|
||||||
"tokio-timer 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-timer 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -1289,7 +1301,7 @@ name = "libp2p-uds"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"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)",
|
||||||
"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)",
|
||||||
@@ -1301,7 +1313,7 @@ name = "libp2p-websocket"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"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)",
|
||||||
"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)",
|
||||||
@@ -1317,7 +1329,7 @@ version = "0.1.0"
|
|||||||
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"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.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -1509,7 +1521,7 @@ version = "0.1.0"
|
|||||||
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"smallvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smallvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -1582,7 +1594,7 @@ 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)",
|
"exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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-primitives 0.1.0",
|
"node-primitives 0.1.0",
|
||||||
"node-runtime 0.1.0",
|
"node-runtime 0.1.0",
|
||||||
@@ -1631,7 +1643,7 @@ dependencies = [
|
|||||||
name = "node-network"
|
name = "node-network"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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-consensus 0.1.0",
|
"node-consensus 0.1.0",
|
||||||
"node-primitives 0.1.0",
|
"node-primitives 0.1.0",
|
||||||
@@ -2169,7 +2181,7 @@ name = "relay"
|
|||||||
version = "0.1.1"
|
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 = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2186,7 +2198,7 @@ version = "0.3.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2248,7 +2260,7 @@ version = "0.1.0"
|
|||||||
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
source = "git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d#8111062f0177fd7423626f2db9560273644a4c4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2807,7 +2819,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"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.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"node-cli 0.1.0",
|
"node-cli 0.1.0",
|
||||||
"vergen 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"vergen 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@@ -2817,7 +2829,7 @@ name = "substrate-bft"
|
|||||||
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)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-codec 2.0.3 (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)",
|
||||||
@@ -2843,7 +2855,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)",
|
||||||
"exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"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)",
|
||||||
"names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -2867,7 +2879,7 @@ 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)",
|
||||||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hash-db 0.9.0 (git+https://github.com/paritytech/trie)",
|
"hash-db 0.9.0 (git+https://github.com/paritytech/trie)",
|
||||||
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"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)",
|
||||||
@@ -2935,6 +2947,23 @@ dependencies = [
|
|||||||
"wasmi 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wasmi 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "substrate-finality-grandpa"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"finality-grandpa 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"futures 0.1.24 (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.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"sr-primitives 0.1.0",
|
||||||
|
"substrate-client 0.1.0",
|
||||||
|
"substrate-keyring 0.1.0",
|
||||||
|
"substrate-network 0.1.0",
|
||||||
|
"substrate-primitives 0.1.0",
|
||||||
|
"tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "substrate-keyring"
|
name = "substrate-keyring"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -2990,7 +3019,7 @@ dependencies = [
|
|||||||
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"error-chain 0.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.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"linked-hash-map 0.5.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)",
|
||||||
"parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -3014,7 +3043,7 @@ dependencies = [
|
|||||||
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"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)",
|
||||||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"libp2p 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
|
"libp2p 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=8111062f0177fd7423626f2db9560273644a4c4d)",
|
||||||
"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)",
|
||||||
@@ -3108,7 +3137,7 @@ version = "0.3.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)",
|
"exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"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.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -3139,7 +3168,7 @@ version = "0.3.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"sr-primitives 0.1.0",
|
"sr-primitives 0.1.0",
|
||||||
"substrate-client 0.1.0",
|
"substrate-client 0.1.0",
|
||||||
@@ -3240,7 +3269,7 @@ name = "substrate-transaction-pool"
|
|||||||
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)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-codec 2.0.3 (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)",
|
||||||
@@ -3424,7 +3453,7 @@ name = "tk-listen"
|
|||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -3435,7 +3464,7 @@ name = "tokio"
|
|||||||
version = "0.1.7"
|
version = "0.1.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-fs 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-fs 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -3453,7 +3482,7 @@ version = "0.1.0"
|
|||||||
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.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -3463,7 +3492,7 @@ version = "0.1.17"
|
|||||||
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.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"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.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -3480,7 +3509,7 @@ name = "tokio-current-thread"
|
|||||||
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"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -3489,7 +3518,7 @@ name = "tokio-dns-unofficial"
|
|||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"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)",
|
||||||
"tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -3500,7 +3529,7 @@ name = "tokio-executor"
|
|||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3508,7 +3537,7 @@ name = "tokio-fs"
|
|||||||
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"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-threadpool 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-threadpool 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@@ -3519,7 +3548,7 @@ version = "0.1.8"
|
|||||||
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.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -3528,7 +3557,7 @@ name = "tokio-proto"
|
|||||||
version = "0.1.1"
|
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 = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
"net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -3545,7 +3574,7 @@ name = "tokio-reactor"
|
|||||||
version = "0.1.1"
|
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 = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mio 0.6.14 (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)",
|
||||||
@@ -3558,7 +3587,7 @@ name = "tokio-service"
|
|||||||
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"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3567,7 +3596,7 @@ 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 = [
|
||||||
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -3580,7 +3609,7 @@ version = "0.1.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crossbeam-deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -3593,7 +3622,7 @@ version = "0.2.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-executor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@@ -3603,7 +3632,7 @@ name = "tokio-tls"
|
|||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -3615,7 +3644,7 @@ version = "0.1.0"
|
|||||||
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.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-io 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -3628,7 +3657,7 @@ version = "0.2.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"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)",
|
||||||
"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)",
|
||||||
@@ -3894,7 +3923,7 @@ name = "want"
|
|||||||
version = "0.0.4"
|
version = "0.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"try-lock 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"try-lock 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@@ -3919,7 +3948,7 @@ dependencies = [
|
|||||||
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -4036,7 +4065,7 @@ version = "0.1.0"
|
|||||||
source = "git+https://github.com/paritytech/yamux#5acf79ecfb69ccdcb65c9f624f285b79716a029d"
|
source = "git+https://github.com/paritytech/yamux#5acf79ecfb69ccdcb65c9f624f285b79716a029d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.24 (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)",
|
||||||
"nohash-hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nohash-hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -4119,6 +4148,7 @@ dependencies = [
|
|||||||
"checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426"
|
"checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426"
|
||||||
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||||
"checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa"
|
"checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa"
|
||||||
|
"checksum finality-grandpa 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7c9a8a25e71e4a11a1a5ef36a9ad09b4ae8c4e0bcf27a900137899ac678b01b0"
|
||||||
"checksum fixed-hash 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d5ec8112f00ea8a483e04748a85522184418fd1cf02890b626d8fc28683f7de"
|
"checksum fixed-hash 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d5ec8112f00ea8a483e04748a85522184418fd1cf02890b626d8fc28683f7de"
|
||||||
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
||||||
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||||
@@ -4126,7 +4156,7 @@ dependencies = [
|
|||||||
"checksum fs-swap 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31a94e9407e53addc49de767234a0b000978523c59117e5badb575ccbb8370f6"
|
"checksum fs-swap 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31a94e9407e53addc49de767234a0b000978523c59117e5badb575ccbb8370f6"
|
||||||
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||||
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||||
"checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c"
|
"checksum futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "0c84b40c7e2de99ffd70602db314a7a8c26b2b3d830e6f7f7a142a8860ab3ca4"
|
||||||
"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
|
"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
|
||||||
"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
|
"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
|
||||||
"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
|
"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ members = [
|
|||||||
"core/client",
|
"core/client",
|
||||||
"core/client/db",
|
"core/client/db",
|
||||||
"core/executor",
|
"core/executor",
|
||||||
|
"core/finality-grandpa",
|
||||||
"core/keyring",
|
"core/keyring",
|
||||||
"core/misbehavior-check",
|
"core/misbehavior-check",
|
||||||
"core/network",
|
"core/network",
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
[package]
|
||||||
|
name = "substrate-finality-grandpa"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
futures = "0.1.17"
|
||||||
|
parity-codec = "2.0"
|
||||||
|
sr-primitives = { path = "../sr-primitives" }
|
||||||
|
substrate-primitives = { path = "../primitives" }
|
||||||
|
substrate-client = { path = "../client" }
|
||||||
|
log = "0.4"
|
||||||
|
tokio = "0.1.7"
|
||||||
|
|
||||||
|
[dependencies.finality-grandpa]
|
||||||
|
version = "0.1.3"
|
||||||
|
features = ["derive-codec"]
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
substrate-network = { path = "../network", features = ["test-helpers"] }
|
||||||
|
parking_lot = "0.4"
|
||||||
|
substrate-keyring = { path = "../keyring" }
|
||||||
@@ -0,0 +1,767 @@
|
|||||||
|
// 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/>.
|
||||||
|
|
||||||
|
//! Integration of the GRANDPA finality gadget into substrate.
|
||||||
|
//!
|
||||||
|
//! This is a long-running future that produces finality notifications.
|
||||||
|
|
||||||
|
extern crate finality_grandpa as grandpa;
|
||||||
|
extern crate futures;
|
||||||
|
extern crate substrate_client as client;
|
||||||
|
extern crate sr_primitives as runtime_primitives;
|
||||||
|
extern crate substrate_primitives;
|
||||||
|
extern crate tokio;
|
||||||
|
extern crate parity_codec as codec;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
extern crate substrate_network as network;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
extern crate parking_lot;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
extern crate substrate_keyring as keyring;
|
||||||
|
|
||||||
|
use futures::prelude::*;
|
||||||
|
use futures::stream::Fuse;
|
||||||
|
use futures::sync::mpsc;
|
||||||
|
use client::{Client, ImportNotifications, backend::Backend, CallExecutor};
|
||||||
|
use codec::{Encode, Decode};
|
||||||
|
use runtime_primitives::traits::{As, NumberFor, Block as BlockT, Header as HeaderT};
|
||||||
|
use runtime_primitives::generic::BlockId;
|
||||||
|
use substrate_primitives::{ed25519, AuthorityId, Blake2Hasher};
|
||||||
|
use tokio::timer::Interval;
|
||||||
|
|
||||||
|
use grandpa::Error as GrandpaError;
|
||||||
|
use grandpa::{voter, round::State as RoundState, Prevote, Precommit, Equivocation};
|
||||||
|
|
||||||
|
use std::collections::{VecDeque, HashMap};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::time::{Instant, Duration};
|
||||||
|
|
||||||
|
const LAST_COMPLETED_KEY: &[u8] = b"grandpa_completed_round";
|
||||||
|
|
||||||
|
/// A GRANDPA message for a substrate chain.
|
||||||
|
pub type Message<Block> = grandpa::Message<<Block as BlockT>::Hash>;
|
||||||
|
/// A signed message.
|
||||||
|
pub type SignedMessage<Block> = grandpa::SignedMessage<<Block as BlockT>::Hash, ed25519::Signature, AuthorityId>;
|
||||||
|
|
||||||
|
/// Configuration for the GRANDPA service.
|
||||||
|
pub struct Config {
|
||||||
|
/// The expected duration for a message to be gossiped across the network.
|
||||||
|
pub gossip_duration: Duration,
|
||||||
|
/// The voters.
|
||||||
|
// TODO: make dynamic
|
||||||
|
pub voters: Vec<AuthorityId>,
|
||||||
|
/// The local signing key.
|
||||||
|
pub local_key: Option<Arc<ed25519::Pair>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Errors that can occur while voting in GRANDPA.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
/// An error within grandpa.
|
||||||
|
Grandpa(GrandpaError),
|
||||||
|
/// A network error.
|
||||||
|
Network(String),
|
||||||
|
/// A blockchain error.
|
||||||
|
Blockchain(String),
|
||||||
|
/// A timer failed to fire.
|
||||||
|
Timer(::tokio::timer::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<GrandpaError> for Error {
|
||||||
|
fn from(e: GrandpaError) -> Self {
|
||||||
|
Error::Grandpa(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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=()>;
|
||||||
|
|
||||||
|
/// Get a stream of messages for a specific round. This stream should
|
||||||
|
/// never logically conclude.
|
||||||
|
fn messages_for(&self, round: u64) -> Self::In;
|
||||||
|
|
||||||
|
/// Send a message at a specific round out.
|
||||||
|
fn send_message(&self, round: u64, message: Vec<u8>);
|
||||||
|
|
||||||
|
/// Clean up messages for a round.
|
||||||
|
fn drop_messages(&self, round: u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Something which can determine if a block is known.
|
||||||
|
pub trait BlockStatus<Block: BlockT> {
|
||||||
|
/// Return `Ok(Some(number))` or `Ok(None)` depending on whether the block
|
||||||
|
/// is definitely known and has been imported.
|
||||||
|
/// If an unexpected error occurs, return that.
|
||||||
|
fn block_number(&self, hash: Block::Hash) -> Result<Option<u32>, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B, E, Block: BlockT> BlockStatus<Block> for Arc<Client<B, E, Block>> where
|
||||||
|
B: Backend<Block, Blake2Hasher>,
|
||||||
|
E: CallExecutor<Block, Blake2Hasher>,
|
||||||
|
NumberFor<Block>: As<u32>,
|
||||||
|
{
|
||||||
|
fn block_number(&self, hash: Block::Hash) -> Result<Option<u32>, Error> {
|
||||||
|
self.block_number_from_id(&BlockId::Hash(hash))
|
||||||
|
.map_err(|e| Error::Blockchain(format!("{:?}", e)))
|
||||||
|
.map(|num| num.map(|n| n.as_()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Buffering imported messages until blocks with given hashes are imported.
|
||||||
|
pub struct UntilImported<Block: BlockT, Status, I> {
|
||||||
|
import_notifications: Fuse<ImportNotifications<Block>>,
|
||||||
|
status_check: Status,
|
||||||
|
inner: Fuse<I>,
|
||||||
|
ready: VecDeque<SignedMessage<Block>>,
|
||||||
|
check_pending: Interval,
|
||||||
|
pending: HashMap<Block::Hash, Vec<SignedMessage<Block>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Block: BlockT, Status: BlockStatus<Block>, I: Stream> UntilImported<Block, Status, I> {
|
||||||
|
fn new(
|
||||||
|
import_notifications: ImportNotifications<Block>,
|
||||||
|
status_check: Status,
|
||||||
|
stream: I,
|
||||||
|
) -> Self {
|
||||||
|
// how often to check if pending messages that are waiting for blocks to be
|
||||||
|
// imported can be checked.
|
||||||
|
//
|
||||||
|
// the import notifications interval takes care of most of this; this is
|
||||||
|
// used in the event of missed import notifications
|
||||||
|
const CHECK_PENDING_INTERVAL: Duration = Duration::from_secs(5);
|
||||||
|
let now = Instant::now();
|
||||||
|
|
||||||
|
let check_pending = Interval::new(now + CHECK_PENDING_INTERVAL, CHECK_PENDING_INTERVAL);
|
||||||
|
UntilImported {
|
||||||
|
import_notifications: import_notifications.fuse(),
|
||||||
|
status_check,
|
||||||
|
inner: stream.fuse(),
|
||||||
|
ready: VecDeque::new(),
|
||||||
|
check_pending,
|
||||||
|
pending: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Block: BlockT, Status: BlockStatus<Block>, I> Stream for UntilImported<Block, Status, I>
|
||||||
|
where I: Stream<Item=SignedMessage<Block>,Error=Error>
|
||||||
|
{
|
||||||
|
type Item = SignedMessage<Block>;
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn poll(&mut self) -> Poll<Option<SignedMessage<Block>>, Error> {
|
||||||
|
loop {
|
||||||
|
match self.inner.poll() {
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
Ok(Async::Ready(None)) => return Ok(Async::Ready(None)),
|
||||||
|
Ok(Async::Ready(Some(signed_message))) => {
|
||||||
|
let (&target_hash, target_number) = signed_message.target();
|
||||||
|
|
||||||
|
// new message: hold it until the block is known.
|
||||||
|
if let Some(number) = self.status_check.block_number(target_hash)? {
|
||||||
|
if number != target_number {
|
||||||
|
warn!(
|
||||||
|
target: "afg",
|
||||||
|
"Authority {:?} signed GRANDPA message with \
|
||||||
|
wrong block number for hash {}",
|
||||||
|
signed_message.id,
|
||||||
|
target_hash
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
self.ready.push_back(signed_message)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.pending.entry(target_hash)
|
||||||
|
.or_insert_with(Vec::new)
|
||||||
|
.push(signed_message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Async::NotReady) => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match self.import_notifications.poll() {
|
||||||
|
Err(_) => return Err(Error::Network(format!("Failed to get new message"))),
|
||||||
|
Ok(Async::Ready(None)) => return Ok(Async::Ready(None)),
|
||||||
|
Ok(Async::Ready(Some(notification))) => {
|
||||||
|
// new block imported. queue up all messages tied to that hash.
|
||||||
|
if let Some(messages) = self.pending.remove(¬ification.hash) {
|
||||||
|
self.ready.extend(messages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Async::NotReady) => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut update_interval = false;
|
||||||
|
while let Async::Ready(Some(_)) = self.check_pending.poll().map_err(Error::Timer)? {
|
||||||
|
update_interval = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if update_interval {
|
||||||
|
let mut known_keys = Vec::new();
|
||||||
|
for &block_hash in self.pending.keys() {
|
||||||
|
if let Some(number) = self.status_check.block_number(block_hash)? {
|
||||||
|
known_keys.push((block_hash, number));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (known_hash, canon_number) in known_keys {
|
||||||
|
if let Some(mut pending_messages) = self.pending.remove(&known_hash) {
|
||||||
|
// verify canonicality of pending messages.
|
||||||
|
pending_messages.retain(|msg| {
|
||||||
|
let number_correct = msg.target().1 == canon_number;
|
||||||
|
if !number_correct {
|
||||||
|
warn!(
|
||||||
|
target: "afg",
|
||||||
|
"Authority {:?} signed GRANDPA message with \
|
||||||
|
wrong block number for hash {}",
|
||||||
|
msg.id,
|
||||||
|
known_hash,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
number_correct
|
||||||
|
});
|
||||||
|
self.ready.extend(pending_messages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ready) = self.ready.pop_front() {
|
||||||
|
return Ok(Async::Ready(Some(ready)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.import_notifications.is_done() && self.inner.is_done() {
|
||||||
|
Ok(Async::Ready(None))
|
||||||
|
} else {
|
||||||
|
Ok(Async::NotReady)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clears the network messages for inner round on drop.
|
||||||
|
struct ClearOnDrop<I, N: Network> {
|
||||||
|
round: u64,
|
||||||
|
inner: I,
|
||||||
|
network: N,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Sink, N: Network> Sink for ClearOnDrop<I, N> {
|
||||||
|
type SinkItem = I::SinkItem;
|
||||||
|
type SinkError = I::SinkError;
|
||||||
|
|
||||||
|
fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
|
||||||
|
self.inner.start_send(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
|
||||||
|
self.inner.poll_complete()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close(&mut self) -> Poll<(), Self::SinkError> {
|
||||||
|
self.inner.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, N: Network> Drop for ClearOnDrop<I, N> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.network.drop_messages(self.round);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// converts a message stream into a stream of signed messages.
|
||||||
|
// the output stream checks signatures also.
|
||||||
|
fn checked_message_stream<Block: BlockT, S>(inner: S, voters: Vec<AuthorityId>)
|
||||||
|
-> impl Stream<Item=SignedMessage<Block>,Error=Error> where
|
||||||
|
S: Stream<Item=Vec<u8>,Error=()>
|
||||||
|
{
|
||||||
|
inner
|
||||||
|
.filter_map(|raw| {
|
||||||
|
let decoded = SignedMessage::<Block>::decode(&mut &raw[..]);
|
||||||
|
if decoded.is_none() {
|
||||||
|
debug!(target: "afg", "Skipping malformed message {:?}", raw);
|
||||||
|
}
|
||||||
|
decoded
|
||||||
|
})
|
||||||
|
.and_then(move |msg| {
|
||||||
|
// check signature.
|
||||||
|
if !voters.contains(&msg.id) {
|
||||||
|
debug!(target: "afg", "Skipping message from unknown voter {}", msg.id);
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let as_public = ::ed25519::Public::from_raw(msg.id.0);
|
||||||
|
let encoded_raw = msg.message.encode();
|
||||||
|
if ::ed25519::verify_strong(&msg.signature, &encoded_raw, as_public) {
|
||||||
|
Ok(Some(msg))
|
||||||
|
} else {
|
||||||
|
debug!(target: "afg", "Skipping message with bad signature");
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter_map(|x| x)
|
||||||
|
.map_err(|()| Error::Network(format!("Failed to receive message on unbounded stream")))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn outgoing_messages<Block: BlockT, N: Network>(
|
||||||
|
local_key: Option<Arc<ed25519::Pair>>,
|
||||||
|
voters: Vec<AuthorityId>,
|
||||||
|
round: u64,
|
||||||
|
network: N,
|
||||||
|
) -> (
|
||||||
|
impl Stream<Item=SignedMessage<Block>,Error=Error>,
|
||||||
|
impl Sink<SinkItem=Message<Block>,SinkError=Error>,
|
||||||
|
) {
|
||||||
|
let locals = local_key.and_then(|pair| {
|
||||||
|
let public = pair.public();
|
||||||
|
voters.iter().find(|id| id.0 == public.0).map(move |id| (pair, id.clone()))
|
||||||
|
});
|
||||||
|
|
||||||
|
let (tx, rx) = mpsc::unbounded();
|
||||||
|
let rx = rx
|
||||||
|
.map(move |msg: Message<Block>| {
|
||||||
|
// when locals exist. sign messages on import
|
||||||
|
if let Some((ref pair, local_id)) = locals {
|
||||||
|
let encoded = msg.encode();
|
||||||
|
let signature = pair.sign(&encoded[..]);
|
||||||
|
let signed = SignedMessage::<Block> {
|
||||||
|
message: msg,
|
||||||
|
signature,
|
||||||
|
id: local_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
// forward to network.
|
||||||
|
network.send_message(round, signed.encode());
|
||||||
|
Some(signed)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter_map(|x| x)
|
||||||
|
.map_err(move |()| Error::Network(
|
||||||
|
format!("Failed to receive on unbounded receiver for round {}", round)
|
||||||
|
));
|
||||||
|
|
||||||
|
let tx = tx.sink_map_err(move |e| Error::Network(format!("Failed to broadcast message \
|
||||||
|
to network in round {}: {:?}", round, e)));
|
||||||
|
|
||||||
|
(rx, tx)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The environment we run GRANDPA in.
|
||||||
|
pub struct Environment<B, E, Block: BlockT, N: Network> {
|
||||||
|
inner: Arc<Client<B, E, Block>>,
|
||||||
|
voters: HashMap<AuthorityId, usize>,
|
||||||
|
config: Config,
|
||||||
|
network: N,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Block: BlockT, B, E, N> grandpa::Chain<Block::Hash> for Environment<B, E, Block, N> where
|
||||||
|
Block: 'static,
|
||||||
|
B: Backend<Block, Blake2Hasher> + 'static,
|
||||||
|
E: CallExecutor<Block, Blake2Hasher> + 'static,
|
||||||
|
N: Network + 'static,
|
||||||
|
N::In: 'static,
|
||||||
|
NumberFor<Block>: As<u32>,
|
||||||
|
{
|
||||||
|
fn ancestry(&self, base: Block::Hash, block: Block::Hash) -> Result<Vec<Block::Hash>, GrandpaError> {
|
||||||
|
let tree_route_res = ::client::blockchain::tree_route(
|
||||||
|
self.inner.backend().blockchain(),
|
||||||
|
BlockId::Hash(block),
|
||||||
|
BlockId::Hash(base),
|
||||||
|
);
|
||||||
|
|
||||||
|
let tree_route = match tree_route_res {
|
||||||
|
Ok(tree_route) => tree_route,
|
||||||
|
Err(e) => {
|
||||||
|
debug!(target: "afg", "Encountered error computing ancestry between block {:?} and base {:?}: {:?}",
|
||||||
|
block, base, e);
|
||||||
|
|
||||||
|
return Err(GrandpaError::NotDescendent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if tree_route.common_block().hash != base {
|
||||||
|
return Err(GrandpaError::NotDescendent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip one because our ancestry is meant to start from the parent of `block`,
|
||||||
|
// and `tree_route` includes it.
|
||||||
|
Ok(tree_route.retracted().iter().skip(1).map(|e| e.hash).collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn best_chain_containing(&self, block: Block::Hash) -> Option<(Block::Hash, u32)> {
|
||||||
|
match self.inner.best_containing(block, None) {
|
||||||
|
Ok(Some(hash)) => {
|
||||||
|
let header = self.inner.header(&BlockId::Hash(hash)).ok()?
|
||||||
|
.expect("Header known to exist after `best_containing` call; qed");
|
||||||
|
|
||||||
|
Some((hash, header.number().as_()))
|
||||||
|
}
|
||||||
|
Ok(None) => None,
|
||||||
|
Err(e) => {
|
||||||
|
debug!(target: "afg", "Encountered error finding best chain containing {:?}: {:?}", block, e);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B, E, Block: BlockT, N> voter::Environment<Block::Hash> for Environment<B, E, Block, N> where
|
||||||
|
Block: 'static,
|
||||||
|
B: Backend<Block, Blake2Hasher> + 'static,
|
||||||
|
E: CallExecutor<Block, Blake2Hasher> + 'static,
|
||||||
|
N: Network + 'static,
|
||||||
|
N::In: 'static,
|
||||||
|
NumberFor<Block>: As<u32>,
|
||||||
|
{
|
||||||
|
type Timer = Box<Future<Item = (), Error = Self::Error>>;
|
||||||
|
type Id = AuthorityId;
|
||||||
|
type Signature = ed25519::Signature;
|
||||||
|
type In = Box<Stream<Item = ::grandpa::SignedMessage<Block::Hash, Self::Signature, Self::Id>, Error = Self::Error>>;
|
||||||
|
type Out = Box<Sink<SinkItem = ::grandpa::Message<Block::Hash>, SinkError = Self::Error>>;
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn round_data(
|
||||||
|
&self,
|
||||||
|
round: u64
|
||||||
|
) -> voter::RoundData<Self::Timer, Self::Id, Self::In, Self::Out> {
|
||||||
|
use client::BlockchainEvents;
|
||||||
|
use tokio::timer::Delay;
|
||||||
|
|
||||||
|
let now = Instant::now();
|
||||||
|
let prevote_timer = Delay::new(now + self.config.gossip_duration * 2);
|
||||||
|
let precommit_timer = Delay::new(now + self.config.gossip_duration * 4);
|
||||||
|
|
||||||
|
// TODO: dispatch this with `mpsc::spawn`.
|
||||||
|
let incoming = checked_message_stream::<Block, _>(
|
||||||
|
self.network.messages_for(round),
|
||||||
|
self.config.voters.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let (out_rx, outgoing) = outgoing_messages::<Block, _>(
|
||||||
|
self.config.local_key.clone(),
|
||||||
|
self.config.voters.clone(),
|
||||||
|
round,
|
||||||
|
self.network.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// schedule incoming messages from the network to be held until
|
||||||
|
// corresponding blocks are imported.
|
||||||
|
let incoming = UntilImported::new(
|
||||||
|
self.inner.import_notification_stream(),
|
||||||
|
self.inner.clone(),
|
||||||
|
incoming,
|
||||||
|
);
|
||||||
|
|
||||||
|
// join incoming network messages with locally originating ones.
|
||||||
|
let incoming = Box::new(incoming.select(out_rx));
|
||||||
|
|
||||||
|
// schedule network message cleanup when sink drops.
|
||||||
|
let outgoing = Box::new(ClearOnDrop {
|
||||||
|
round,
|
||||||
|
network: self.network.clone(),
|
||||||
|
inner: outgoing,
|
||||||
|
});
|
||||||
|
|
||||||
|
voter::RoundData {
|
||||||
|
prevote_timer: Box::new(prevote_timer.map_err(Error::Timer)),
|
||||||
|
precommit_timer: Box::new(precommit_timer.map_err(Error::Timer)),
|
||||||
|
voters: self.voters.clone(),
|
||||||
|
incoming,
|
||||||
|
outgoing,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn completed(&self, round: u64, state: RoundState<Block::Hash>) {
|
||||||
|
let encoded_state = (round, state).encode();
|
||||||
|
if let Err(e) = self.inner.backend()
|
||||||
|
.insert_aux(&[(LAST_COMPLETED_KEY, &encoded_state[..])], &[])
|
||||||
|
{
|
||||||
|
warn!(target: "afg", "Error bookkeeping last completed round in DB: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize_block(&self, hash: Block::Hash, number: u32) {
|
||||||
|
// TODO: don't unconditionally notify.
|
||||||
|
if let Err(e) = self.inner.finalize_block(BlockId::Hash(hash), true) {
|
||||||
|
warn!(target: "afg", "Error applying finality to block {:?}: {:?}", (hash, number), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prevote_equivocation(
|
||||||
|
&self,
|
||||||
|
_round: u64,
|
||||||
|
equivocation: ::grandpa::Equivocation<Self::Id, Prevote<Block::Hash>, Self::Signature>
|
||||||
|
) {
|
||||||
|
warn!(target: "afg", "Detected prevote equivocation in the finality worker: {:?}", equivocation);
|
||||||
|
// nothing yet; this could craft misbehavior reports of some kind.
|
||||||
|
}
|
||||||
|
|
||||||
|
fn precommit_equivocation(
|
||||||
|
&self,
|
||||||
|
_round: u64,
|
||||||
|
equivocation: Equivocation<Self::Id, Precommit<Block::Hash>, Self::Signature>
|
||||||
|
) {
|
||||||
|
warn!(target: "afg", "Detected precommit equivocation in the finality worker: {:?}", equivocation);
|
||||||
|
// nothing yet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run a GRANDPA voter as a task. The returned future should be executed in a tokio runtime.
|
||||||
|
pub fn run_voter<B, E, Block: BlockT, N>(
|
||||||
|
config: Config,
|
||||||
|
client: Arc<Client<B, E, Block>>,
|
||||||
|
voters: HashMap<AuthorityId, usize>,
|
||||||
|
network: N,
|
||||||
|
) -> Result<impl Future<Item=(),Error=()>,client::error::Error> where
|
||||||
|
Block::Hash: Ord,
|
||||||
|
B: Backend<Block, Blake2Hasher> + 'static,
|
||||||
|
E: CallExecutor<Block, Blake2Hasher> + 'static,
|
||||||
|
N: Network + 'static,
|
||||||
|
N::In: 'static,
|
||||||
|
NumberFor<Block>: As<u32>,
|
||||||
|
{
|
||||||
|
let chain_info = client.info()?;
|
||||||
|
let genesis_hash = chain_info.chain.genesis_hash;
|
||||||
|
let last_finalized = (
|
||||||
|
chain_info.chain.finalized_hash,
|
||||||
|
chain_info.chain.finalized_number.as_()
|
||||||
|
);
|
||||||
|
|
||||||
|
let (last_round_number, last_state) = match client.backend().get_aux(LAST_COMPLETED_KEY)? {
|
||||||
|
None => (0, RoundState::genesis((genesis_hash, 0))),
|
||||||
|
Some(raw) => <(u64, RoundState<Block::Hash>)>::decode(&mut &raw[..])
|
||||||
|
.ok_or_else(|| ::client::error::ErrorKind::Backend(
|
||||||
|
format!("Last GRANDPA round state kept in invalid format")
|
||||||
|
))?
|
||||||
|
};
|
||||||
|
|
||||||
|
let environment = Arc::new(Environment {
|
||||||
|
inner: client,
|
||||||
|
config,
|
||||||
|
voters,
|
||||||
|
network,
|
||||||
|
});
|
||||||
|
|
||||||
|
let voter = voter::Voter::new(
|
||||||
|
environment,
|
||||||
|
last_round_number,
|
||||||
|
last_state,
|
||||||
|
last_finalized,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(voter.map_err(|e| warn!("GRANDPA Voter failed: {:?}", e)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use network::test::*;
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
use tokio::runtime::current_thread;
|
||||||
|
use keyring::Keyring;
|
||||||
|
use client::BlockchainEvents;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct TestGrandpaNetwork {
|
||||||
|
inner: Arc<Mutex<TestNet>>,
|
||||||
|
peer_id: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestGrandpaNetwork {
|
||||||
|
fn new(inner: Arc<Mutex<TestNet>>, peer_id: usize,) -> Self {
|
||||||
|
TestGrandpaNetwork {
|
||||||
|
inner,
|
||||||
|
peer_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn round_to_topic(round: u64) -> Hash {
|
||||||
|
let mut hash = Hash::default();
|
||||||
|
round.using_encoded(|s| {
|
||||||
|
let raw = hash.as_mut();
|
||||||
|
raw[..8].copy_from_slice(s);
|
||||||
|
});
|
||||||
|
hash
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Network for TestGrandpaNetwork {
|
||||||
|
type In = Box<Stream<Item=Vec<u8>,Error=()>>;
|
||||||
|
|
||||||
|
fn messages_for(&self, round: u64) -> Self::In {
|
||||||
|
use network::consensus_gossip::ConsensusMessage;
|
||||||
|
|
||||||
|
let messages = self.inner.lock().peer(self.peer_id)
|
||||||
|
.with_spec(|spec, _| spec.gossip.messages_for(round_to_topic(round)));
|
||||||
|
|
||||||
|
let messages = messages
|
||||||
|
.map_err(
|
||||||
|
move |_| panic!("Messages for round {} dropped too early", round)
|
||||||
|
)
|
||||||
|
.map(|msg| match msg {
|
||||||
|
ConsensusMessage::ChainSpecific(raw, _) => {
|
||||||
|
let message = GossipMessage::decode(&mut &raw[..]).unwrap();
|
||||||
|
message.data
|
||||||
|
}
|
||||||
|
_ => panic!("Only chain-specific messages come under this stream"),
|
||||||
|
});
|
||||||
|
|
||||||
|
Box::new(messages)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_message(&self, round: u64, message: Vec<u8>) {
|
||||||
|
let mut inner = self.inner.lock();
|
||||||
|
inner.peer(self.peer_id).gossip_message(round_to_topic(round), message);
|
||||||
|
inner.route();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drop_messages(&self, round: u64) {
|
||||||
|
let topic = round_to_topic(round);
|
||||||
|
self.inner.lock().peer(self.peer_id)
|
||||||
|
.with_spec(|spec, _| spec.gossip.collect_garbage(|t| t == &topic));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const TEST_GOSSIP_DURATION: Duration = Duration::from_millis(500);
|
||||||
|
const TEST_ROUTING_INTERVAL: Duration = Duration::from_millis(50);
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn finalize_20_unanimous_3_peers() {
|
||||||
|
let mut net = TestNet::new(3);
|
||||||
|
net.peer(0).push_blocks(20, false);
|
||||||
|
net.sync();
|
||||||
|
|
||||||
|
let net = Arc::new(Mutex::new(net));
|
||||||
|
let peers = &[
|
||||||
|
(0, Keyring::Alice),
|
||||||
|
(1, Keyring::Bob),
|
||||||
|
(2, Keyring::Charlie),
|
||||||
|
];
|
||||||
|
|
||||||
|
let voters: Vec<_> = peers.iter()
|
||||||
|
.map(|&(_, ref key)| AuthorityId(key.to_raw_public()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut finality_notifications = Vec::new();
|
||||||
|
|
||||||
|
let mut runtime = current_thread::Runtime::new().unwrap();
|
||||||
|
for (peer_id, key) in peers {
|
||||||
|
let client = net.lock().peer(*peer_id).client().clone();
|
||||||
|
finality_notifications.push(
|
||||||
|
client.finality_notification_stream()
|
||||||
|
.take_while(|n| Ok(n.header.number() < &20))
|
||||||
|
.for_each(move |_| Ok(()))
|
||||||
|
);
|
||||||
|
let voter = run_voter(
|
||||||
|
Config {
|
||||||
|
gossip_duration: TEST_GOSSIP_DURATION,
|
||||||
|
voters: voters.clone(),
|
||||||
|
local_key: Some(Arc::new(key.clone().into())),
|
||||||
|
},
|
||||||
|
client,
|
||||||
|
voters.iter().map(|&id| (id, 1)).collect(),
|
||||||
|
TestGrandpaNetwork::new(net.clone(), *peer_id),
|
||||||
|
).expect("all in order with client and network");
|
||||||
|
|
||||||
|
runtime.spawn(voter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for all finalized on each.
|
||||||
|
let wait_for = ::futures::future::join_all(finality_notifications)
|
||||||
|
.map(|_| ())
|
||||||
|
.map_err(|_| ());
|
||||||
|
|
||||||
|
let drive_to_completion = ::tokio::timer::Interval::new_interval(TEST_ROUTING_INTERVAL)
|
||||||
|
.for_each(move |_| { net.lock().route_until_complete(); Ok(()) })
|
||||||
|
.map(|_| ())
|
||||||
|
.map_err(|_| ());
|
||||||
|
|
||||||
|
runtime.block_on(wait_for.select(drive_to_completion).map_err(|_| ())).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn observer_can_finalize() {
|
||||||
|
let mut net = TestNet::new(4);
|
||||||
|
net.peer(0).push_blocks(20, false);
|
||||||
|
net.sync();
|
||||||
|
|
||||||
|
let net = Arc::new(Mutex::new(net));
|
||||||
|
let peers = &[
|
||||||
|
(0, Keyring::Alice),
|
||||||
|
(1, Keyring::Bob),
|
||||||
|
(2, Keyring::Charlie),
|
||||||
|
];
|
||||||
|
|
||||||
|
let voters: HashMap<_, _> = peers.iter()
|
||||||
|
.map(|&(_, ref key)| (AuthorityId(key.to_raw_public()), 1))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut finality_notifications = Vec::new();
|
||||||
|
|
||||||
|
let mut runtime = current_thread::Runtime::new().unwrap();
|
||||||
|
let all_peers = peers.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(|(id, key)| (id, Some(Arc::new(key.into()))))
|
||||||
|
.chain(::std::iter::once((3, None)));
|
||||||
|
|
||||||
|
for (peer_id, local_key) in all_peers {
|
||||||
|
let client = net.lock().peer(peer_id).client().clone();
|
||||||
|
finality_notifications.push(
|
||||||
|
client.finality_notification_stream()
|
||||||
|
.take_while(|n| Ok(n.header.number() < &20))
|
||||||
|
.for_each(move |_| Ok(()))
|
||||||
|
);
|
||||||
|
let voter = run_voter(
|
||||||
|
Config {
|
||||||
|
gossip_duration: TEST_GOSSIP_DURATION,
|
||||||
|
voters: voters.keys().cloned().collect(),
|
||||||
|
local_key,
|
||||||
|
},
|
||||||
|
client,
|
||||||
|
voters.clone(),
|
||||||
|
TestGrandpaNetwork::new(net.clone(), peer_id),
|
||||||
|
).expect("all in order with client and network");
|
||||||
|
|
||||||
|
runtime.spawn(voter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for all finalized on each.
|
||||||
|
let wait_for = ::futures::future::join_all(finality_notifications)
|
||||||
|
.map(|_| ())
|
||||||
|
.map_err(|_| ());
|
||||||
|
|
||||||
|
let drive_to_completion = ::tokio::timer::Interval::new_interval(TEST_ROUTING_INTERVAL)
|
||||||
|
.for_each(move |_| { net.lock().route_until_complete(); Ok(()) })
|
||||||
|
.map(|_| ())
|
||||||
|
.map_err(|_| ());
|
||||||
|
|
||||||
|
runtime.block_on(wait_for.select(drive_to_completion).map_err(|_| ())).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,7 +23,15 @@ parity-codec = "2.0"
|
|||||||
parity-codec-derive = "2.0"
|
parity-codec-derive = "2.0"
|
||||||
substrate-network-libp2p = { path = "../../core/network-libp2p" }
|
substrate-network-libp2p = { path = "../../core/network-libp2p" }
|
||||||
|
|
||||||
|
env_logger = { version = "0.4", optional = true }
|
||||||
|
substrate-keyring = { path = "../../core/keyring", optional = true }
|
||||||
|
substrate-test-client = { path = "../../core/test-client", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
env_logger = "0.4"
|
env_logger = { version = "0.4" }
|
||||||
substrate-keyring = { path = "../../core/keyring" }
|
substrate-keyring = { path = "../../core/keyring" }
|
||||||
substrate-test-client = { path = "../../core/test-client" }
|
substrate-test-client = { path = "../../core/test-client" }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
|
test-helpers = ["env_logger", "substrate-keyring", "substrate-test-client"]
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ struct MessageEntry<B: BlockT> {
|
|||||||
/// Consensus network protocol handler. Manages statements and candidate requests.
|
/// Consensus network protocol handler. Manages statements and candidate requests.
|
||||||
pub struct ConsensusGossip<B: BlockT> {
|
pub struct ConsensusGossip<B: BlockT> {
|
||||||
peers: HashMap<NodeIndex, PeerConsensus<B::Hash>>,
|
peers: HashMap<NodeIndex, PeerConsensus<B::Hash>>,
|
||||||
message_sink: Option<(mpsc::UnboundedSender<ConsensusMessage<B>>, B::Hash)>,
|
live_message_sinks: HashMap<B::Hash, mpsc::UnboundedSender<ConsensusMessage<B>>>,
|
||||||
messages: Vec<MessageEntry<B>>,
|
messages: Vec<MessageEntry<B>>,
|
||||||
message_hashes: HashSet<B::Hash>,
|
message_hashes: HashSet<B::Hash>,
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ impl<B: BlockT> ConsensusGossip<B> where B::Header: HeaderT<Number=u64> {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
ConsensusGossip {
|
ConsensusGossip {
|
||||||
peers: HashMap::new(),
|
peers: HashMap::new(),
|
||||||
message_sink: None,
|
live_message_sinks: HashMap::new(),
|
||||||
messages: Default::default(),
|
messages: Default::default(),
|
||||||
message_hashes: Default::default(),
|
message_hashes: Default::default(),
|
||||||
}
|
}
|
||||||
@@ -72,7 +72,7 @@ impl<B: BlockT> ConsensusGossip<B> where B::Header: HeaderT<Number=u64> {
|
|||||||
|
|
||||||
/// Closes all notification streams.
|
/// Closes all notification streams.
|
||||||
pub fn abort(&mut self) {
|
pub fn abort(&mut self) {
|
||||||
self.message_sink = None;
|
self.live_message_sinks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle new connected peer.
|
/// Handle new connected peer.
|
||||||
@@ -150,23 +150,23 @@ impl<B: BlockT> ConsensusGossip<B> where B::Header: HeaderT<Number=u64> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Handles incoming chain-specific message and repropagates
|
/// Handles incoming chain-specific message and repropagates
|
||||||
pub fn on_chain_specific(&mut self, protocol: &mut Context<B>, who: NodeIndex, message: Vec<u8>, parent_hash: B::Hash) {
|
pub fn on_chain_specific(&mut self, protocol: &mut Context<B>, who: NodeIndex, message: Vec<u8>, topic: B::Hash) {
|
||||||
debug!(target: "gossip", "received chain-specific gossip message");
|
debug!(target: "gossip", "received chain-specific gossip message");
|
||||||
if let Some((hash, message)) = self.handle_incoming(protocol, who, ConsensusMessage::ChainSpecific(message, parent_hash)) {
|
if let Some((hash, message)) = self.handle_incoming(protocol, who, ConsensusMessage::ChainSpecific(message, topic)) {
|
||||||
debug!(target: "gossip", "handled incoming chain-specific message");
|
debug!(target: "gossip", "handled incoming chain-specific message");
|
||||||
// propagate to other peers.
|
// propagate to other peers.
|
||||||
self.multicast(protocol, message, Some(hash));
|
self.multicast(protocol, message, Some(hash));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a stream of messages relevant to consensus on top of a given parent hash.
|
/// Get a stream of messages relevant to consensus for the given topic.
|
||||||
pub fn messages_for(&mut self, parent_hash: B::Hash) -> mpsc::UnboundedReceiver<ConsensusMessage<B>> {
|
pub fn messages_for(&mut self, topic: B::Hash) -> mpsc::UnboundedReceiver<ConsensusMessage<B>> {
|
||||||
let (sink, stream) = mpsc::unbounded();
|
let (sink, stream) = mpsc::unbounded();
|
||||||
|
|
||||||
for entry in self.messages.iter() {
|
for entry in self.messages.iter() {
|
||||||
let message_matches = match entry.message {
|
let message_matches = match entry.message {
|
||||||
ConsensusMessage::Bft(ref msg) => msg.parent_hash == parent_hash,
|
ConsensusMessage::Bft(ref msg) => msg.parent_hash == topic,
|
||||||
ConsensusMessage::ChainSpecific(_, ref h) => h == &parent_hash,
|
ConsensusMessage::ChainSpecific(_, ref h) => h == &topic,
|
||||||
};
|
};
|
||||||
|
|
||||||
if message_matches {
|
if message_matches {
|
||||||
@@ -174,14 +174,14 @@ impl<B: BlockT> ConsensusGossip<B> where B::Header: HeaderT<Number=u64> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.message_sink = Some((sink, parent_hash));
|
self.live_message_sinks.insert(topic, sink);
|
||||||
stream
|
stream
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Multicast a chain-specific message to other authorities.
|
/// Multicast a chain-specific message to other authorities.
|
||||||
pub fn multicast_chain_specific(&mut self, protocol: &mut Context<B>, message: Vec<u8>, parent_hash: B::Hash) {
|
pub fn multicast_chain_specific(&mut self, protocol: &mut Context<B>, message: Vec<u8>, topic: B::Hash) {
|
||||||
trace!(target:"gossip", "sending chain-specific message");
|
trace!(target:"gossip", "sending chain-specific message");
|
||||||
self.multicast(protocol, ConsensusMessage::ChainSpecific(message, parent_hash), None);
|
self.multicast(protocol, ConsensusMessage::ChainSpecific(message, topic), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Multicast a BFT message to other authorities
|
/// Multicast a BFT message to other authorities
|
||||||
@@ -196,20 +196,21 @@ impl<B: BlockT> ConsensusGossip<B> where B::Header: HeaderT<Number=u64> {
|
|||||||
self.peers.remove(&who);
|
self.peers.remove(&who);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prune old or no longer relevant consensus messages.
|
/// Prune old or no longer relevant consensus messages. Provide a predicate
|
||||||
/// Supply an optional block hash where consensus is known to have concluded.
|
/// for pruning, which returns `false` when the items with a given topic should be pruned.
|
||||||
pub fn collect_garbage(&mut self, best_hash: Option<&B::Hash>) {
|
pub fn collect_garbage<P: Fn(&B::Hash) -> bool>(&mut self, predicate: P) {
|
||||||
|
self.live_message_sinks.retain(|_, sink| !sink.is_closed());
|
||||||
|
|
||||||
let hashes = &mut self.message_hashes;
|
let hashes = &mut self.message_hashes;
|
||||||
let before = self.messages.len();
|
let before = self.messages.len();
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
self.messages.retain(|entry| {
|
self.messages.retain(|entry| {
|
||||||
if entry.instant + MESSAGE_LIFETIME >= now &&
|
let topic = match entry.message {
|
||||||
best_hash.map_or(true, |parent_hash|
|
ConsensusMessage::Bft(ref msg) => &msg.parent_hash,
|
||||||
match entry.message {
|
ConsensusMessage::ChainSpecific(_, ref h) => h,
|
||||||
ConsensusMessage::Bft(ref msg) => &msg.parent_hash != parent_hash,
|
};
|
||||||
ConsensusMessage::ChainSpecific(_, ref h) => h != parent_hash,
|
|
||||||
})
|
if entry.instant + MESSAGE_LIFETIME >= now && predicate(topic) {
|
||||||
{
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
hashes.remove(&entry.hash);
|
hashes.remove(&entry.hash);
|
||||||
@@ -223,7 +224,7 @@ impl<B: BlockT> ConsensusGossip<B> where B::Header: HeaderT<Number=u64> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_incoming(&mut self, protocol: &mut Context<B>, who: NodeIndex, message: ConsensusMessage<B>) -> Option<(B::Hash, ConsensusMessage<B>)> {
|
fn handle_incoming(&mut self, protocol: &mut Context<B>, who: NodeIndex, message: ConsensusMessage<B>) -> Option<(B::Hash, ConsensusMessage<B>)> {
|
||||||
let (hash, parent, message) = match message {
|
let (hash, topic, message) = match message {
|
||||||
ConsensusMessage::Bft(msg) => {
|
ConsensusMessage::Bft(msg) => {
|
||||||
let parent = msg.parent_hash;
|
let parent = msg.parent_hash;
|
||||||
let generic = GenericMessage::BftMessage(msg);
|
let generic = GenericMessage::BftMessage(msg);
|
||||||
@@ -236,13 +237,13 @@ impl<B: BlockT> ConsensusGossip<B> where B::Header: HeaderT<Number=u64> {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ConsensusMessage::ChainSpecific(msg, parent) => {
|
ConsensusMessage::ChainSpecific(msg, topic) => {
|
||||||
let generic = GenericMessage::ChainSpecific(msg);
|
let generic = GenericMessage::ChainSpecific(msg);
|
||||||
(
|
(
|
||||||
::protocol::hash_message::<B>(&generic),
|
::protocol::hash_message::<B>(&generic),
|
||||||
parent,
|
topic,
|
||||||
match generic {
|
match generic {
|
||||||
GenericMessage::ChainSpecific(msg) => ConsensusMessage::ChainSpecific(msg, parent),
|
GenericMessage::ChainSpecific(msg) => ConsensusMessage::ChainSpecific(msg, topic),
|
||||||
_ => panic!("`generic` is known to be the `ChainSpecific` variant; qed"),
|
_ => panic!("`generic` is known to be the `ChainSpecific` variant; qed"),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -254,14 +255,14 @@ impl<B: BlockT> ConsensusGossip<B> where B::Header: HeaderT<Number=u64> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
match (protocol.client().info(), protocol.client().header(&BlockId::Hash(parent))) {
|
match (protocol.client().info(), protocol.client().header(&BlockId::Hash(topic))) {
|
||||||
(_, Err(e)) | (Err(e), _) => {
|
(_, Err(e)) | (Err(e), _) => {
|
||||||
debug!(target:"gossip", "Error reading blockchain: {:?}", e);
|
debug!(target:"gossip", "Error reading blockchain: {:?}", e);
|
||||||
return None;
|
return None;
|
||||||
},
|
},
|
||||||
(Ok(info), Ok(Some(header))) => {
|
(Ok(info), Ok(Some(header))) => {
|
||||||
if header.number() < &info.chain.best_number {
|
if header.number() < &info.chain.best_number {
|
||||||
trace!(target:"gossip", "Ignored ancient message from {}, hash={}", who, parent);
|
trace!(target:"gossip", "Ignored ancient message from {}, hash={}", who, topic);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -269,16 +270,17 @@ impl<B: BlockT> ConsensusGossip<B> where B::Header: HeaderT<Number=u64> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref mut peer) = self.peers.get_mut(&who) {
|
if let Some(ref mut peer) = self.peers.get_mut(&who) {
|
||||||
|
use std::collections::hash_map::Entry;
|
||||||
peer.known_messages.insert(hash);
|
peer.known_messages.insert(hash);
|
||||||
if let Some((sink, parent_hash)) = self.message_sink.take() {
|
if let Entry::Occupied(mut entry) = self.live_message_sinks.entry(topic) {
|
||||||
if parent == parent_hash {
|
debug!(target: "gossip", "Pushing relevant consensus message to sink.");
|
||||||
debug!(target: "gossip", "Pushing relevant consensus message to sink.");
|
if let Err(e) = entry.get().unbounded_send(message.clone()) {
|
||||||
if let Err(e) = sink.unbounded_send(message.clone()) {
|
trace!(target:"gossip", "Error broadcasting message notification: {:?}", e);
|
||||||
trace!(target:"gossip", "Error broadcasting message notification: {:?}", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.message_sink = Some((sink, parent_hash));
|
if entry.get().is_closed() {
|
||||||
|
entry.remove_entry();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
trace!(target:"gossip", "Ignored statement from unregistered peer {}", who);
|
trace!(target:"gossip", "Ignored statement from unregistered peer {}", who);
|
||||||
@@ -344,7 +346,7 @@ mod tests {
|
|||||||
consensus.message_hashes.insert(m2_hash);
|
consensus.message_hashes.insert(m2_hash);
|
||||||
|
|
||||||
// nothing to collect
|
// nothing to collect
|
||||||
consensus.collect_garbage(None);
|
consensus.collect_garbage(|_topic| true);
|
||||||
assert_eq!(consensus.messages.len(), 2);
|
assert_eq!(consensus.messages.len(), 2);
|
||||||
assert_eq!(consensus.message_hashes.len(), 2);
|
assert_eq!(consensus.message_hashes.len(), 2);
|
||||||
|
|
||||||
@@ -357,13 +359,13 @@ mod tests {
|
|||||||
digest: Default::default(),
|
digest: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
consensus.collect_garbage(Some(&H256::default()));
|
consensus.collect_garbage(|&topic| topic != Default::default());
|
||||||
assert_eq!(consensus.messages.len(), 2);
|
assert_eq!(consensus.messages.len(), 2);
|
||||||
assert_eq!(consensus.message_hashes.len(), 2);
|
assert_eq!(consensus.message_hashes.len(), 2);
|
||||||
|
|
||||||
// header that matches one of the messages
|
// header that matches one of the messages
|
||||||
header.parent_hash = prev_hash;
|
header.parent_hash = prev_hash;
|
||||||
consensus.collect_garbage(Some(&prev_hash));
|
consensus.collect_garbage(|topic| topic != &prev_hash);
|
||||||
assert_eq!(consensus.messages.len(), 1);
|
assert_eq!(consensus.messages.len(), 1);
|
||||||
assert_eq!(consensus.message_hashes.len(), 1);
|
assert_eq!(consensus.message_hashes.len(), 1);
|
||||||
assert!(consensus.message_hashes.contains(&m2_hash));
|
assert!(consensus.message_hashes.contains(&m2_hash));
|
||||||
@@ -371,7 +373,7 @@ mod tests {
|
|||||||
// make timestamp expired
|
// make timestamp expired
|
||||||
consensus.messages.clear();
|
consensus.messages.clear();
|
||||||
push_msg!(m2_hash, now - MESSAGE_LIFETIME, m2);
|
push_msg!(m2_hash, now - MESSAGE_LIFETIME, m2);
|
||||||
consensus.collect_garbage(None);
|
consensus.collect_garbage(|_topic| true);
|
||||||
assert!(consensus.messages.is_empty());
|
assert!(consensus.messages.is_empty());
|
||||||
assert!(consensus.message_hashes.is_empty());
|
assert!(consensus.message_hashes.is_empty());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ enum SyncLink<'a, B: 'a + BlockT, E: 'a + ExecuteInContext<B>> {
|
|||||||
/// Indirect link (through service).
|
/// Indirect link (through service).
|
||||||
Indirect(&'a RwLock<ChainSync<B>>, &'a Client<B>, &'a E),
|
Indirect(&'a RwLock<ChainSync<B>>, &'a Client<B>, &'a E),
|
||||||
/// Direct references are given.
|
/// Direct references are given.
|
||||||
#[cfg(test)]
|
#[cfg(any(test, feature = "test-helpers"))]
|
||||||
Direct(&'a mut ChainSync<B>, &'a mut Context<B>),
|
Direct(&'a mut ChainSync<B>, &'a mut Context<B>),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,7 +402,7 @@ impl<'a, B: 'static + BlockT, E: 'a + ExecuteInContext<B>> SyncLink<'a, B, E> {
|
|||||||
/// Execute closure with locked ChainSync.
|
/// Execute closure with locked ChainSync.
|
||||||
fn with_sync<F: Fn(&mut ChainSync<B>, &mut Context<B>)>(&mut self, closure: F) {
|
fn with_sync<F: Fn(&mut ChainSync<B>, &mut Context<B>)>(&mut self, closure: F) {
|
||||||
match *self {
|
match *self {
|
||||||
#[cfg(test)]
|
#[cfg(any(test, feature = "test-helpers"))]
|
||||||
SyncLink::Direct(ref mut sync, ref mut protocol) =>
|
SyncLink::Direct(ref mut sync, ref mut protocol) =>
|
||||||
closure(*sync, *protocol),
|
closure(*sync, *protocol),
|
||||||
SyncLink::Indirect(ref sync, _, ref service) =>
|
SyncLink::Indirect(ref sync, _, ref service) =>
|
||||||
@@ -417,7 +417,7 @@ impl<'a, B: 'static + BlockT, E: 'a + ExecuteInContext<B>> SyncLink<'a, B, E> {
|
|||||||
impl<'a, B: 'static + BlockT, E: ExecuteInContext<B>> SyncLinkApi<B> for SyncLink<'a, B, E> {
|
impl<'a, B: 'static + BlockT, E: ExecuteInContext<B>> SyncLinkApi<B> for SyncLink<'a, B, E> {
|
||||||
fn chain(&self) -> &Client<B> {
|
fn chain(&self) -> &Client<B> {
|
||||||
match *self {
|
match *self {
|
||||||
#[cfg(test)]
|
#[cfg(any(test, feature = "test-helpers"))]
|
||||||
SyncLink::Direct(_, ref protocol) => protocol.client(),
|
SyncLink::Direct(_, ref protocol) => protocol.client(),
|
||||||
SyncLink::Indirect(_, ref chain, _) => *chain,
|
SyncLink::Indirect(_, ref chain, _) => *chain,
|
||||||
}
|
}
|
||||||
@@ -447,6 +447,40 @@ impl<'a, B: 'static + BlockT, E: ExecuteInContext<B>> SyncLinkApi<B> for SyncLin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Blocks import queue that is importing blocks in the same thread.
|
||||||
|
/// The boolean value indicates whether blocks should be imported without instant finality.
|
||||||
|
#[cfg(any(test, feature = "test-helpers"))]
|
||||||
|
pub struct SyncImportQueue(pub bool);
|
||||||
|
|
||||||
|
#[cfg(any(test, feature = "test-helpers"))]
|
||||||
|
impl<B: 'static + BlockT> ImportQueue<B> for SyncImportQueue {
|
||||||
|
fn clear(&self) { }
|
||||||
|
|
||||||
|
fn stop(&self) { }
|
||||||
|
|
||||||
|
fn status(&self) -> ImportQueueStatus<B> {
|
||||||
|
ImportQueueStatus {
|
||||||
|
importing_count: 0,
|
||||||
|
best_importing_number: Zero::zero(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_importing(&self, _hash: &B::Hash) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn import_blocks(&self, sync: &mut ChainSync<B>, protocol: &mut Context<B>, blocks: (BlockOrigin, Vec<BlockData<B>>)) {
|
||||||
|
struct DummyExecuteInContext;
|
||||||
|
|
||||||
|
impl<B: 'static + BlockT> ExecuteInContext<B> for DummyExecuteInContext {
|
||||||
|
fn execute_in_context<F: Fn(&mut Context<B>)>(&self, _closure: F) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
import_many_blocks(&mut SyncLink::Direct::<_, DummyExecuteInContext>(sync, protocol), None, blocks, self.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
use client;
|
use client;
|
||||||
@@ -457,35 +491,6 @@ pub mod tests {
|
|||||||
use runtime_primitives::generic::BlockId;
|
use runtime_primitives::generic::BlockId;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// Blocks import queue that is importing blocks in the same thread.
|
|
||||||
/// The boolean value indicates whether blocks should be imported without instant finality.
|
|
||||||
pub struct SyncImportQueue(pub bool);
|
|
||||||
struct DummyExecuteInContext;
|
|
||||||
|
|
||||||
impl<B: 'static + BlockT> ExecuteInContext<B> for DummyExecuteInContext {
|
|
||||||
fn execute_in_context<F: Fn(&mut Context<B>)>(&self, _closure: F) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<B: 'static + BlockT> ImportQueue<B> for SyncImportQueue {
|
|
||||||
fn clear(&self) { }
|
|
||||||
|
|
||||||
fn stop(&self) { }
|
|
||||||
|
|
||||||
fn status(&self) -> ImportQueueStatus<B> {
|
|
||||||
ImportQueueStatus {
|
|
||||||
importing_count: 0,
|
|
||||||
best_importing_number: Zero::zero(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_importing(&self, _hash: &B::Hash) -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn import_blocks(&self, sync: &mut ChainSync<B>, protocol: &mut Context<B>, blocks: (BlockOrigin, Vec<BlockData<B>>)) {
|
|
||||||
import_many_blocks(&mut SyncLink::Direct::<_, DummyExecuteInContext>(sync, protocol), None, blocks, self.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct TestLink {
|
struct TestLink {
|
||||||
chain: Arc<Client<Block>>,
|
chain: Arc<Client<Block>>,
|
||||||
|
|||||||
@@ -37,9 +37,14 @@ extern crate rand;
|
|||||||
#[macro_use] extern crate error_chain;
|
#[macro_use] extern crate error_chain;
|
||||||
#[macro_use] extern crate parity_codec_derive;
|
#[macro_use] extern crate parity_codec_derive;
|
||||||
|
|
||||||
#[cfg(test)] extern crate env_logger;
|
#[cfg(test)]
|
||||||
#[cfg(test)] extern crate substrate_keyring as keyring;
|
extern crate env_logger;
|
||||||
#[cfg(test)] extern crate substrate_test_client as test_client;
|
|
||||||
|
#[cfg(any(test, feature = "test-helpers"))]
|
||||||
|
extern crate substrate_keyring as keyring;
|
||||||
|
|
||||||
|
#[cfg(any(test, feature = "test-helpers"))]
|
||||||
|
extern crate substrate_test_client as test_client;
|
||||||
|
|
||||||
mod service;
|
mod service;
|
||||||
mod sync;
|
mod sync;
|
||||||
@@ -55,7 +60,8 @@ pub mod error;
|
|||||||
pub mod message;
|
pub mod message;
|
||||||
pub mod specialization;
|
pub mod specialization;
|
||||||
|
|
||||||
#[cfg(test)] mod test;
|
#[cfg(any(test, feature = "test-helpers"))]
|
||||||
|
pub mod test;
|
||||||
|
|
||||||
pub use chain::Client as ClientHandle;
|
pub use chain::Client as ClientHandle;
|
||||||
pub use service::{Service, FetchFuture, ConsensusService, BftMessageStream,
|
pub use service::{Service, FetchFuture, ConsensusService, BftMessageStream,
|
||||||
|
|||||||
@@ -14,6 +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/>.
|
||||||
|
|
||||||
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
mod sync;
|
mod sync;
|
||||||
|
|
||||||
use std::collections::{VecDeque, HashSet, HashMap};
|
use std::collections::{VecDeque, HashSet, HashMap};
|
||||||
@@ -22,7 +25,6 @@ use std::sync::Arc;
|
|||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use client;
|
use client;
|
||||||
use client::block_builder::BlockBuilder;
|
use client::block_builder::BlockBuilder;
|
||||||
use runtime_primitives::traits::Block as BlockT;
|
|
||||||
use runtime_primitives::generic::BlockId;
|
use runtime_primitives::generic::BlockId;
|
||||||
use io::SyncIo;
|
use io::SyncIo;
|
||||||
use protocol::{Context, Protocol};
|
use protocol::{Context, Protocol};
|
||||||
@@ -31,27 +33,45 @@ use config::ProtocolConfig;
|
|||||||
use service::TransactionPool;
|
use service::TransactionPool;
|
||||||
use network_libp2p::{NodeIndex, SessionInfo, Severity};
|
use network_libp2p::{NodeIndex, SessionInfo, Severity};
|
||||||
use keyring::Keyring;
|
use keyring::Keyring;
|
||||||
use codec::Encode;
|
use codec::{Encode, Decode};
|
||||||
use import_queue::tests::SyncImportQueue;
|
use import_queue::SyncImportQueue;
|
||||||
use test_client::{self, TestClient};
|
use test_client::{self, TestClient};
|
||||||
use test_client::runtime::{Block, Hash, Transfer, Extrinsic};
|
|
||||||
use specialization::Specialization;
|
use specialization::Specialization;
|
||||||
|
use consensus_gossip::ConsensusGossip;
|
||||||
|
|
||||||
pub struct DummySpecialization;
|
pub use test_client::runtime::{Block, Hash, Transfer, Extrinsic};
|
||||||
|
|
||||||
|
/// The test specialization.
|
||||||
|
pub struct DummySpecialization {
|
||||||
|
/// Consensus gossip handle.
|
||||||
|
pub gossip: ConsensusGossip<Block>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Encode, Decode)]
|
||||||
|
pub struct GossipMessage {
|
||||||
|
/// The topic to classify under.
|
||||||
|
pub topic: Hash,
|
||||||
|
/// The data to send.
|
||||||
|
pub data: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Specialization<Block> for DummySpecialization {
|
impl Specialization<Block> for DummySpecialization {
|
||||||
fn status(&self) -> Vec<u8> { vec![] }
|
fn status(&self) -> Vec<u8> { vec![] }
|
||||||
|
|
||||||
fn on_connect(&mut self, _ctx: &mut Context<Block>, _peer_id: NodeIndex, _status: ::message::Status<Block>) {
|
fn on_connect(&mut self, ctx: &mut Context<Block>, peer_id: NodeIndex, status: ::message::Status<Block>) {
|
||||||
|
self.gossip.new_peer(ctx, peer_id, status.roles);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_disconnect(&mut self, _ctx: &mut Context<Block>, _peer_id: NodeIndex) {
|
fn on_disconnect(&mut self, ctx: &mut Context<Block>, peer_id: NodeIndex) {
|
||||||
|
self.gossip.peer_disconnected(ctx, peer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_message(&mut self, _ctx: &mut Context<Block>, _peer_id: NodeIndex, _message: ::message::Message<Block>) {
|
fn on_message(&mut self, ctx: &mut Context<Block>, peer_id: NodeIndex, message: ::message::Message<Block>) {
|
||||||
|
if let ::message::generic::Message::ChainSpecific(data) = message {
|
||||||
|
let gossip_message = GossipMessage::decode(&mut &data[..])
|
||||||
|
.expect("gossip messages all in known format; qed");
|
||||||
|
self.gossip.on_chain_specific(ctx, peer_id, data, gossip_message.topic)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,19 +193,30 @@ impl Peer {
|
|||||||
fn flush(&self) {
|
fn flush(&self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_blocks<F>(&self, count: usize, mut edit_block: F)
|
/// Push a message into the gossip network and relay to peers.
|
||||||
|
/// `TestNet::sync_step` needs to be called to ensure it's propagated.
|
||||||
|
pub fn gossip_message(&self, topic: Hash, data: Vec<u8>) {
|
||||||
|
self.sync.with_spec(&mut TestIo::new(&self.queue, None), |spec, ctx| {
|
||||||
|
let message = GossipMessage { topic, data }.encode();
|
||||||
|
spec.gossip.multicast_chain_specific(ctx, message, topic);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add blocks to the peer -- edit the block before adding
|
||||||
|
pub fn generate_blocks<F>(&self, count: usize, 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 {}, (#{})", block.hash(), block.header.number);
|
trace!("Generating {}, (#{}, parent={})", block.header.hash(), block.header.number, block.header.parent_hash);
|
||||||
self.client.justify_and_import(client::BlockOrigin::File, block).unwrap();
|
self.client.justify_and_import(client::BlockOrigin::File, block).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_blocks(&self, count: usize, with_tx: bool) {
|
/// Push blocks to the peer (simplified: with or without a TX)
|
||||||
|
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, |builder| {
|
||||||
@@ -203,6 +234,18 @@ impl Peer {
|
|||||||
self.generate_blocks(count, |_| ());
|
self.generate_blocks(count, |_| ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Execute a function with specialization for this peer.
|
||||||
|
pub fn with_spec<F, U>(&self, f: F) -> U
|
||||||
|
where F: FnOnce(&mut DummySpecialization, &mut Context<Block>) -> U
|
||||||
|
{
|
||||||
|
self.sync.with_spec(&mut TestIo::new(&self.queue, None), f)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the client.
|
||||||
|
pub fn client(&self) -> &Arc<client::Client<test_client::Backend, test_client::Executor, Block>> {
|
||||||
|
&self.client
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EmptyTransactionPool;
|
pub struct EmptyTransactionPool;
|
||||||
@@ -226,11 +269,13 @@ pub struct TestNet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TestNet {
|
impl TestNet {
|
||||||
fn new(n: usize) -> Self {
|
/// Create new test network with this many peers.
|
||||||
|
pub fn new(n: usize) -> Self {
|
||||||
Self::new_with_config(n, ProtocolConfig::default())
|
Self::new_with_config(n, ProtocolConfig::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_with_config(n: usize, config: ProtocolConfig) -> Self {
|
/// Create new test network with peers and given config.
|
||||||
|
pub fn new_with_config(n: usize, config: ProtocolConfig) -> Self {
|
||||||
let mut net = TestNet {
|
let mut net = TestNet {
|
||||||
peers: Vec::new(),
|
peers: Vec::new(),
|
||||||
started: false,
|
started: false,
|
||||||
@@ -243,11 +288,23 @@ impl TestNet {
|
|||||||
net
|
net
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add a peer.
|
||||||
pub fn add_peer(&mut self, config: &ProtocolConfig) {
|
pub 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(false));
|
let import_queue = Arc::new(SyncImportQueue(false));
|
||||||
let sync = Protocol::new(config.clone(), client.clone(), import_queue, None, tx_pool, DummySpecialization).unwrap();
|
let specialization = DummySpecialization {
|
||||||
|
gossip: ConsensusGossip::new(),
|
||||||
|
};
|
||||||
|
let sync = Protocol::new(
|
||||||
|
config.clone(),
|
||||||
|
client.clone(),
|
||||||
|
import_queue,
|
||||||
|
None,
|
||||||
|
tx_pool,
|
||||||
|
specialization
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
self.peers.push(Arc::new(Peer {
|
self.peers.push(Arc::new(Peer {
|
||||||
sync: sync,
|
sync: sync,
|
||||||
client: client,
|
client: client,
|
||||||
@@ -255,10 +312,12 @@ impl TestNet {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get reference to peer.
|
||||||
pub fn peer(&self, i: usize) -> &Peer {
|
pub fn peer(&self, i: usize) -> &Peer {
|
||||||
&self.peers[i]
|
&self.peers[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Start network.
|
||||||
fn start(&mut self) {
|
fn start(&mut self) {
|
||||||
if self.started {
|
if self.started {
|
||||||
return;
|
return;
|
||||||
@@ -274,7 +333,8 @@ impl TestNet {
|
|||||||
self.started = true;
|
self.started = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync_step(&mut self) {
|
/// Do one step of routing.
|
||||||
|
pub fn route(&mut self) {
|
||||||
for peer in 0..self.peers.len() {
|
for peer in 0..self.peers.len() {
|
||||||
let packet = self.peers[peer].pending_message();
|
let packet = self.peers[peer].pending_message();
|
||||||
if let Some(packet) = packet {
|
if let Some(packet) = packet {
|
||||||
@@ -294,20 +354,32 @@ impl TestNet {
|
|||||||
self.peers[*d].on_disconnect(peer as NodeIndex);
|
self.peers[*d].on_disconnect(peer as NodeIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.sync_step_peer(peer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync_step_peer(&mut self, peer_num: usize) {
|
/// Route messages between peers until all queues are empty.
|
||||||
self.peers[peer_num].sync_step();
|
pub fn route_until_complete(&mut self) {
|
||||||
|
while !self.done() {
|
||||||
|
self.route()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn restart_peer(&mut self, i: usize) {
|
/// Do a step of synchronization.
|
||||||
|
pub fn sync_step(&mut self) {
|
||||||
|
self.route();
|
||||||
|
|
||||||
|
for peer in &mut self.peers {
|
||||||
|
peer.sync_step();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Restart sync for a peer.
|
||||||
|
pub fn restart_peer(&mut self, i: usize) {
|
||||||
self.peers[i].restart_sync();
|
self.peers[i].restart_sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync(&mut self) -> u32 {
|
/// Perform synchronization until complete.
|
||||||
|
pub 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() {
|
||||||
@@ -317,14 +389,16 @@ impl TestNet {
|
|||||||
total_steps
|
total_steps
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync_steps(&mut self, count: usize) {
|
/// Do the given amount of sync steps.
|
||||||
|
pub 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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn done(&self) -> bool {
|
/// Whether all peers have synced.
|
||||||
|
pub fn done(&self) -> bool {
|
||||||
self.peers.iter().all(|p| p.is_done())
|
self.peers.iter().all(|p| p.is_done())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,8 @@ impl Protocol {
|
|||||||
fn new_consensus(&mut self, parent_hash: Hash) {
|
fn new_consensus(&mut self, parent_hash: Hash) {
|
||||||
let old_consensus = self.live_consensus.take();
|
let old_consensus = self.live_consensus.take();
|
||||||
self.live_consensus = Some(parent_hash);
|
self.live_consensus = Some(parent_hash);
|
||||||
self.consensus_gossip.collect_garbage(old_consensus.as_ref());
|
self.consensus_gossip
|
||||||
|
.collect_garbage(|topic| old_consensus.as_ref().map_or(true, |h| topic != h));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +106,7 @@ impl Specialization<Block> for Protocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn maintain_peers(&mut self, _ctx: &mut Context<Block>) {
|
fn maintain_peers(&mut self, _ctx: &mut Context<Block>) {
|
||||||
self.consensus_gossip.collect_garbage(None);
|
self.consensus_gossip.collect_garbage(|_| true);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_block_imported(&mut self, _ctx: &mut Context<Block>, _hash: Hash, _header: &Header) {
|
fn on_block_imported(&mut self, _ctx: &mut Context<Block>, _hash: Hash, _header: &Header) {
|
||||||
|
|||||||
Reference in New Issue
Block a user