Add a substrate-peerset crate (#2042)

* Add a substrate-peerset crate

* Some adjustements

* More adjustements

* Use a temporary libp2p branch

* Add back-off mechanism

* Fix RPC tests

* Some adjustements

* Another libp2p bugfix

* Do a round-robin in the peerset

* Use a real dependency instead of a patch for libp2p

* Initialize reserved nodes correctly

* Better diagnostic for no address

* Don't allocate slots if in reserved only

* Ban node on dial failure

* Fix indentation
This commit is contained in:
Pierre Krieger
2019-03-21 14:02:28 +01:00
committed by Robert Habermeier
parent f6f15b618e
commit 90c6f85db5
17 changed files with 1255 additions and 1517 deletions
+115 -97
View File
@@ -1287,30 +1287,30 @@ dependencies = [
[[package]]
name = "libp2p"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core-derive 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-dns 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-floodsub 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-identify 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-kad 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-mdns 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-mplex 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-noise 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-ping 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-plaintext 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-ratelimit 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-secio 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-tcp 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-uds 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-websocket 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-yamux 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"libp2p-core-derive 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"libp2p-dns 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"libp2p-floodsub 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"libp2p-identify 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"libp2p-kad 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"libp2p-mdns 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"libp2p-mplex 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"libp2p-noise 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"libp2p-ping 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"libp2p-plaintext 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"libp2p-ratelimit 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"libp2p-secio 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"libp2p-tcp 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"libp2p-uds 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"libp2p-websocket 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"libp2p-yamux 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"stdweb 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1322,7 +1322,7 @@ dependencies = [
[[package]]
name = "libp2p-core"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1333,15 +1333,15 @@ dependencies = [
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"multistream-select 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"multistream-select 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"protobuf 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rw-stream-sink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rw-stream-sink 0.1.1 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
"sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1357,7 +1357,7 @@ dependencies = [
[[package]]
name = "libp2p-core-derive"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1366,12 +1366,12 @@ dependencies = [
[[package]]
name = "libp2p-dns"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1379,14 +1379,14 @@ dependencies = [
[[package]]
name = "libp2p-floodsub"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"cuckoofilter 0.3.2 (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.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"protobuf 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1398,14 +1398,14 @@ dependencies = [
[[package]]
name = "libp2p-identify"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"bytes 0.4.11 (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.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"protobuf 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1419,7 +1419,7 @@ dependencies = [
[[package]]
name = "libp2p-kad"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"bigint 4.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1427,12 +1427,12 @@ dependencies = [
"bytes 0.4.11 (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.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-identify 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-ping 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"libp2p-identify 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"libp2p-ping 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"protobuf 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1447,15 +1447,15 @@ dependencies = [
[[package]]
name = "libp2p-mdns"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1468,12 +1468,12 @@ dependencies = [
[[package]]
name = "libp2p-mplex"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"bytes 0.4.11 (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.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1484,12 +1484,12 @@ dependencies = [
[[package]]
name = "libp2p-noise"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1502,14 +1502,14 @@ dependencies = [
[[package]]
name = "libp2p-ping"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1521,21 +1521,21 @@ dependencies = [
[[package]]
name = "libp2p-plaintext"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libp2p-ratelimit"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"aio-limited 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1544,7 +1544,7 @@ dependencies = [
[[package]]
name = "libp2p-secio"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1553,12 +1553,12 @@ dependencies = [
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"protobuf 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rw-stream-sink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rw-stream-sink 0.1.1 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
"sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"stdweb 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1570,12 +1570,12 @@ dependencies = [
[[package]]
name = "libp2p-tcp"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1584,25 +1584,25 @@ dependencies = [
[[package]]
name = "libp2p-uds"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libp2p-websocket"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rw-stream-sink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"rw-stream-sink 0.1.1 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"stdweb 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"websocket 0.22.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1611,10 +1611,10 @@ dependencies = [
[[package]]
name = "libp2p-yamux"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"yamux 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1807,7 +1807,7 @@ dependencies = [
[[package]]
name = "multistream-select"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2179,13 +2179,13 @@ dependencies = [
[[package]]
name = "parity-multiaddr"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
"unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -2193,7 +2193,7 @@ dependencies = [
[[package]]
name = "parity-multihash"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2728,7 +2728,7 @@ dependencies = [
[[package]]
name = "rw-stream-sink"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#afd9623fccaac5ce1c41db1d82ad4def2652390f"
dependencies = [
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3943,6 +3943,7 @@ dependencies = [
"substrate-consensus-common 0.1.0",
"substrate-keyring 0.1.0",
"substrate-network-libp2p 0.1.0",
"substrate-peerset 0.1.0",
"substrate-primitives 0.1.0",
"substrate-test-client 0.1.0",
"tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3958,7 +3959,7 @@ dependencies = [
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3966,6 +3967,7 @@ dependencies = [
"serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-peerset 0.1.0",
"tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3982,6 +3984,22 @@ dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "substrate-peerset"
version = "0.1.0"
dependencies = [
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libp2p 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "substrate-primitives"
version = "0.1.0"
@@ -5165,24 +5183,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047"
"checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2"
"checksum libp2p 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96bec5a2470cf03c5f0a74c55fc7b26fe969a1530d09d40e02ed76b287e3f9d9"
"checksum libp2p-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d53c885b93897902e5fdfd02340459bd940e970b73dd2cf506d4009e527489bf"
"checksum libp2p-core-derive 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e00ab475ca93c07ce539691003b682a0ff025f7dfb51e4ab29f5474457ded59b"
"checksum libp2p-dns 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "983bc7e80b6b5c89f5c6b674880bc058d37f481812692431914732ee2aeaf87a"
"checksum libp2p-floodsub 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aca5042008a7f7ddc53f5d40e6411ffebd66af22989a364303f2996fc5f39c79"
"checksum libp2p-identify 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9036ddde527bba0ae8a9037af7637c6c7a10ccdcdff6d2b00e7fe01f7620d400"
"checksum libp2p-kad 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9f42265a4ad1c3a153465babcf64ea32d33b3872f4e2a27fb1dc3d1ed9301fd"
"checksum libp2p-mdns 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "260cb7644da51ee2680c6413d350cee35441e78699b38e63600397867e32e3ab"
"checksum libp2p-mplex 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "938678badaa29182f826308d86a89db53b99dd401121c551a979fd1b0a87af48"
"checksum libp2p-noise 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8820b79d0967de619e5dc991f84ffd5b888d06969bc62cf041412b2e9fc1e5c"
"checksum libp2p-ping 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad1b0983dbc2bf126583555c7a855ceaa28abfe764b9ede087d308b80ff7b2a"
"checksum libp2p-plaintext 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7cb42f7def0cb74781f6793f0fecbcfa0db79baee80adf18215abc30b1b6912c"
"checksum libp2p-ratelimit 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f6971c2fc1cd938cd702b2320d3b5e3b5a353b1a3310de974769c3fa670d26e"
"checksum libp2p-secio 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48a881b9c1b6ff0d35d985437d9f59d2d3ee2c529375aa188a978a1bd1d6f261"
"checksum libp2p-tcp 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79583caf603d93dc43ee314409c57e070e9a70c760631eea91822a25e898d1af"
"checksum libp2p-uds 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d72965117a6b0ead9b78af8682b0ab6d8c3d71dbb9aadbcb947ef2ef78c2c8a"
"checksum libp2p-websocket 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b69b73fcef9d58ae90c6742389a1d29e14dcf3a4ab30bba2f0ca7e984fa59f9f"
"checksum libp2p-yamux 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "563222e2c303516fa097686573f003ee74761eb8d6b6df4204ae1aa07f5dc16c"
"checksum libp2p 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum libp2p-core-derive 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum libp2p-dns 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum libp2p-floodsub 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum libp2p-identify 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum libp2p-kad 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum libp2p-mdns 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum libp2p-mplex 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum libp2p-noise 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum libp2p-ping 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum libp2p-plaintext 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum libp2p-ratelimit 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum libp2p-secio 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum libp2p-tcp 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum libp2p-uds 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum libp2p-websocket 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum libp2p-yamux 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum librocksdb-sys 5.14.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b9024327233e7fac7982440f73301c00046d438c5b1011e8f4e394226ce19007"
"checksum libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "688e8d65e495567c2c35ea0001b26b9debf0b4ea11f8cccc954233b75fc3428a"
"checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939"
@@ -5204,7 +5222,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40"
"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125"
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
"checksum multistream-select 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ed84364f0e921a32204896952ee80c7befc14a7a39f2c56cd955d71e8dae6"
"checksum multistream-select 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef320dab323286b50fb5cdda23f61c796a72a89998ab565ca32525c5c556f2da"
"checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2"
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
@@ -5227,8 +5245,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21c9c3a1623c71ed83964ff28cac6126e178920f7646d32c337eacb9152b2907"
"checksum parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "864e9f66b58c0b38f0d6b511b6576afa2b678ae801b64220553bced57ac12df9"
"checksum parity-crypto 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b9db194dfbcfe3b398d63d765437a5c7232d59906e203055f0e993f6458ff1"
"checksum parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61ae6944d4435d41f4d0f12108c5cbb9207cbb14bc8f2b4984c6e930dc9c8e41"
"checksum parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e8eab0287ccde7821e337a124dc5a4f1d6e4c25d10cc91e3f9361615dd95076"
"checksum parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)" = "511379a8194230c2395d2f5fa627a5a7e108a9f976656ce723ae68fca4097bfc"
"checksum parity-ws 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2fec5048fba72a2e01baeb0d08089db79aead4b57e2443df172fb1840075a233"
"checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac"
@@ -5288,7 +5306,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum rw-stream-sink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d548a40fe17c3a77d54b82457b79fcc9b8a288d509ca20fbf5aa1dac386d22d6"
"checksum rw-stream-sink 0.1.1 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "<none>"
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
"checksum safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f7bf422d23a88c16d5090d455f182bc99c60af4df6a345c63428acf5129e347"
"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9"
+1
View File
@@ -100,3 +100,4 @@ is-it-maintained-open-issues = { repository = "paritytech/substrate" }
[profile.release]
# Substrate runtime requires unwinding.
panic = "unwind"
+2 -1
View File
@@ -13,7 +13,7 @@ bytes = "0.4"
error-chain = { version = "0.12", default-features = false }
fnv = "1.0"
futures = "0.1"
libp2p = { version = "0.5.0", default-features = false, features = ["secio-secp256k1", "libp2p-websocket"] }
libp2p = { git = "https://github.com/tomaka/libp2p-rs", branch = "substrate-tmp-2019-03-20", default-features = false, features = ["secio-secp256k1", "libp2p-websocket"] }
parking_lot = "0.7.1"
lazy_static = "1.2"
log = "0.4"
@@ -22,6 +22,7 @@ serde = "1.0.70"
serde_derive = "1.0.70"
serde_json = "1.0.24"
smallvec = "0.6"
substrate-peerset = { path = "../peerset" }
tokio = "0.1"
tokio-io = "0.1"
tokio-timer = "0.2"
+59 -104
View File
@@ -15,14 +15,13 @@
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
use crate::custom_proto::{CustomProto, CustomProtoOut, RegisteredProtocol};
use crate::NetworkConfiguration;
use futures::prelude::*;
use libp2p::NetworkBehaviour;
use libp2p::core::{Multiaddr, PeerId, ProtocolsHandler, PublicKey};
use libp2p::core::swarm::{ConnectedPoint, NetworkBehaviour, NetworkBehaviourAction};
use libp2p::core::swarm::{NetworkBehaviourEventProcess, PollParameters};
use libp2p::identify::{Identify, IdentifyEvent, protocol::IdentifyInfo};
use libp2p::kad::{Kademlia, KademliaOut, KadConnectionType};
use libp2p::kad::{Kademlia, KademliaOut};
use libp2p::ping::{Ping, PingEvent};
use log::{debug, trace, warn};
use std::{cmp, io, fmt, time::Duration, time::Instant};
@@ -50,21 +49,35 @@ pub struct Behaviour<TMessage, TSubstream> {
impl<TMessage, TSubstream> Behaviour<TMessage, TSubstream> {
/// Builds a new `Behaviour`.
// TODO: redundancy between config and local_public_key (https://github.com/libp2p/rust-libp2p/issues/745)
pub fn new(config: &NetworkConfiguration, local_public_key: PublicKey, protocols: RegisteredProtocol<TMessage>) -> Self {
pub fn new(
user_agent: String,
local_public_key: PublicKey,
protocol: RegisteredProtocol<TMessage>,
known_addresses: Vec<(PeerId, Multiaddr)>,
peerset: substrate_peerset::PeersetMut,
) -> Self {
let identify = {
let proto_version = "/substrate/1.0".to_string();
let user_agent = format!("{} ({})", config.client_version, config.node_name);
Identify::new(proto_version, user_agent, local_public_key.clone())
};
let local_peer_id = local_public_key.into_peer_id();
let custom_protocols = CustomProto::new(config, &local_peer_id, protocols);
let custom_protocols = CustomProto::new(protocol, peerset);
let mut kademlia = Kademlia::without_init(local_public_key.into_peer_id());
for (peer_id, addr) in &known_addresses {
kademlia.add_connected_address(peer_id, addr.clone());
}
kademlia.initialize();
Behaviour {
ping: Ping::new(),
custom_protocols,
discovery: DiscoveryBehaviour::new(local_peer_id),
discovery: DiscoveryBehaviour {
user_defined: known_addresses,
kademlia,
next_kad_random_query: Delay::new(Instant::now()),
duration_to_next_kad: Duration::from_secs(60),
},
identify,
events: Vec::new(),
}
@@ -81,67 +94,9 @@ impl<TMessage, TSubstream> Behaviour<TMessage, TSubstream> {
self.custom_protocols.send_packet(target, data)
}
/// Returns the number of peers in the topology.
pub fn num_topology_peers(&self) -> usize {
self.custom_protocols.num_topology_peers()
}
/// Flushes the topology to the disk.
pub fn flush_topology(&mut self) -> Result<(), io::Error> {
self.custom_protocols.flush_topology()
}
/// Perform a cleanup pass, removing all obsolete addresses and peers.
///
/// This should be done from time to time.
pub fn cleanup(&mut self) {
self.custom_protocols.cleanup();
}
/// Returns the list of reserved nodes.
pub fn reserved_peers(&self) -> impl Iterator<Item = &PeerId> {
self.custom_protocols.reserved_peers()
}
/// Try to add a reserved peer.
pub fn add_reserved_peer(&mut self, peer_id: PeerId, addr: Multiaddr) {
self.custom_protocols.add_reserved_peer(peer_id, addr)
}
/// Try to remove a reserved peer.
///
/// If we are in reserved mode and we were connected to a node with this peer ID, then this
/// method will disconnect it and return its index.
pub fn remove_reserved_peer(&mut self, peer_id: PeerId) {
self.custom_protocols.remove_reserved_peer(peer_id)
}
/// Returns true if we only accept reserved nodes.
pub fn is_reserved_only(&self) -> bool {
self.custom_protocols.is_reserved_only()
}
/// Start accepting all peers again if we weren't.
pub fn accept_unreserved_peers(&mut self) {
self.custom_protocols.accept_unreserved_peers()
}
/// Start refusing non-reserved nodes. Returns the list of nodes that have been disconnected.
pub fn deny_unreserved_peers(&mut self) {
self.custom_protocols.deny_unreserved_peers()
}
/// Disconnects a peer and bans it for a little while.
///
/// Same as `drop_node`, except that the same peer will not be able to reconnect later.
#[inline]
pub fn ban_node(&mut self, peer_id: PeerId) {
self.custom_protocols.ban_peer(peer_id)
}
/// Returns a list of all the peers that are banned, and until when.
pub fn banned_nodes(&self) -> impl Iterator<Item = (&PeerId, Instant)> {
self.custom_protocols.banned_peers()
/// Returns the list of nodes that we know exist in the network.
pub fn known_peers(&self) -> impl Iterator<Item = &PeerId> {
self.discovery.kademlia.kbuckets_entries()
}
/// Returns true if we try to open protocols with the given peer.
@@ -154,6 +109,13 @@ impl<TMessage, TSubstream> Behaviour<TMessage, TSubstream> {
self.custom_protocols.is_open(peer_id)
}
/// Adds a hard-coded address for the given peer, that never expires.
pub fn add_known_address(&mut self, peer_id: PeerId, addr: Multiaddr) {
if self.discovery.user_defined.iter().all(|(p, a)| *p != peer_id && *a != addr) {
self.discovery.user_defined.push((peer_id, addr));
}
}
/// Disconnects the custom protocols from a peer.
///
/// The peer will still be able to use Kademlia or other protocols, but will get disconnected
@@ -167,16 +129,6 @@ impl<TMessage, TSubstream> Behaviour<TMessage, TSubstream> {
pub fn drop_node(&mut self, peer_id: &PeerId) {
self.custom_protocols.disconnect_peer(peer_id)
}
/// Returns the list of peers in the topology.
pub fn known_peers(&self) -> impl Iterator<Item = &PeerId> {
self.custom_protocols.known_peers()
}
/// Returns a list of addresses known for this peer, and their reputation score.
pub fn known_addresses(&mut self, peer_id: &PeerId) -> impl Iterator<Item = (&Multiaddr, u32)> {
self.custom_protocols.known_addresses(peer_id)
}
}
/// Event that can be emitted by the behaviour.
@@ -283,10 +235,7 @@ impl<TMessage, TSubstream> NetworkBehaviourEventProcess<IdentifyEvent> for Behav
for addr in &info.listen_addrs {
self.discovery.kademlia.add_connected_address(&peer_id, addr.clone());
}
self.custom_protocols.add_discovered_addrs(
&peer_id,
info.listen_addrs.iter().map(|addr| (addr.clone(), true))
);
self.custom_protocols.add_discovered_node(&peer_id);
self.events.push(BehaviourOut::Identified { peer_id, info });
}
IdentifyEvent::Error { .. } => {}
@@ -301,17 +250,16 @@ impl<TMessage, TSubstream> NetworkBehaviourEventProcess<IdentifyEvent> for Behav
impl<TMessage, TSubstream> NetworkBehaviourEventProcess<KademliaOut> for Behaviour<TMessage, TSubstream> {
fn inject_event(&mut self, out: KademliaOut) {
match out {
KademliaOut::Discovered { peer_id, addresses, ty } => {
self.custom_protocols.add_discovered_addrs(
&peer_id,
addresses.into_iter().map(|addr| (addr, ty == KadConnectionType::Connected))
);
KademliaOut::Discovered { .. } => {}
KademliaOut::KBucketAdded { peer_id, .. } => {
self.custom_protocols.add_discovered_node(&peer_id);
}
KademliaOut::FindNodeResult { key, closer_peers } => {
trace!(target: "sub-libp2p", "Kademlia query for {:?} yielded {:?} results",
trace!(target: "sub-libp2p", "Libp2p => Query for {:?} yielded {:?} results",
key, closer_peers.len());
if closer_peers.is_empty() {
warn!(target: "sub-libp2p", "Kademlia random query has yielded empty results");
warn!(target: "sub-libp2p", "Libp2p => Random Kademlia query has yielded empty \
results");
}
}
// We never start any GET_PROVIDERS query.
@@ -343,6 +291,9 @@ impl<TMessage, TSubstream> Behaviour<TMessage, TSubstream> {
/// Implementation of `NetworkBehaviour` that discovers the nodes on the network.
pub struct DiscoveryBehaviour<TSubstream> {
/// User-defined list of nodes and their addresses. Typically includes bootstrap nodes and
/// reserved nodes.
user_defined: Vec<(PeerId, Multiaddr)>,
/// Kademlia requests and answers.
kademlia: Kademlia<TSubstream>,
/// Stream that fires when we need to perform the next random Kademlia query.
@@ -351,16 +302,6 @@ pub struct DiscoveryBehaviour<TSubstream> {
duration_to_next_kad: Duration,
}
impl<TSubstream> DiscoveryBehaviour<TSubstream> {
fn new(local_peer_id: PeerId) -> Self {
DiscoveryBehaviour {
kademlia: Kademlia::without_init(local_peer_id),
next_kad_random_query: Delay::new(Instant::now()),
duration_to_next_kad: Duration::from_secs(1),
}
}
}
impl<TSubstream> NetworkBehaviour for DiscoveryBehaviour<TSubstream>
where
TSubstream: AsyncRead + AsyncWrite,
@@ -373,7 +314,21 @@ where
}
fn addresses_of_peer(&mut self, peer_id: &PeerId) -> Vec<Multiaddr> {
self.kademlia.addresses_of_peer(peer_id)
let mut list = self.user_defined.iter()
.filter_map(|(p, a)| if p == peer_id { Some(a.clone()) } else { None })
.collect::<Vec<_>>();
list.extend(self.kademlia.addresses_of_peer(peer_id));
trace!(target: "sub-libp2p", "Addresses of {:?} are {:?}", peer_id, list);
if list.is_empty() {
if self.kademlia.kbuckets_entries().any(|p| p == peer_id) {
debug!(target: "sub-libp2p", "Requested dialing to {:?} (peer in k-buckets), \
and no address was found", peer_id);
} else {
debug!(target: "sub-libp2p", "Requested dialing to {:?} (peer not in k-buckets), \
and no address was found", peer_id);
}
}
list
}
fn inject_connected(&mut self, peer_id: PeerId, endpoint: ConnectedPoint) {
@@ -417,8 +372,8 @@ where
Ok(Async::NotReady) => break,
Ok(Async::Ready(_)) => {
let random_peer_id = PeerId::random();
debug!(target: "sub-libp2p", "Starting random Kademlia request for {:?}",
random_peer_id);
debug!(target: "sub-libp2p", "Libp2p <= Starting random Kademlia request for \
{:?}", random_peer_id);
self.kademlia.find_node(random_peer_id);
// Reset the `Delay` to the next random.
@@ -427,7 +382,7 @@ where
Duration::from_secs(60));
},
Err(err) => {
warn!(target: "sub-libp2p", "Kad query timer errored: {:?}", err);
warn!(target: "sub-libp2p", "Kademlia query timer errored: {:?}", err);
break
}
}
File diff suppressed because it is too large Load Diff
@@ -799,10 +799,6 @@ where TSubstream: AsyncRead + AsyncWrite, TMessage: CustomMessage {
is_severe,
error: Box::new(err),
}));
// If we failed to open a substream, there is little chance that we manage to open any
// other substream ever again on this connection, and thus we disable the handler.
self.disable();
}
fn connection_keep_alive(&self) -> KeepAlive {
@@ -19,5 +19,4 @@ pub use self::upgrade::{CustomMessage, CustomMessageId, RegisteredProtocol};
mod behaviour;
mod handler;
mod topology;
mod upgrade;
@@ -1,725 +0,0 @@
// Copyright 2018-2019 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/>.?
use fnv::FnvHashMap;
use libp2p::{core::swarm::ConnectedPoint, Multiaddr, PeerId};
use log::{debug, info, trace, warn};
use serde_derive::{Serialize, Deserialize};
use std::{cmp, fs};
use std::io::{Read, Cursor, Error as IoError, ErrorKind as IoErrorKind, Write, BufReader, BufWriter};
use std::path::{Path, PathBuf};
use std::time::{Duration, Instant, SystemTime};
/// For each address we're connected to, a period of this duration increases the score by 1.
const CONNEC_DURATION_PER_SCORE: Duration = Duration::from_secs(10);
/// Maximum number of addresses for a given peer. If there are more than this number of addresses,
/// the ones with a lower score will be removed.
const MAX_ADDRESSES_PER_PEER: usize = 10;
/// Maximum value for the score.
const MAX_SCORE: u32 = 100;
/// When we successfully connect to a node, raises its score to the given minimum value.
const CONNECTED_MINIMUM_SCORE: u32 = 20;
/// Initial score that a node discovered through Kademlia receives, where we have a hint that the
/// node is reachable.
const DISCOVERY_INITIAL_SCORE_CONNECTABLE: u32 = 15;
/// Initial score that a node discovered through Kademlia receives, without any hint.
const DISCOVERY_INITIAL_SCORE: u32 = 10;
/// Score adjustement when we fail to connect to an address.
const SCORE_DIFF_ON_FAILED_TO_CONNECT: i32 = -1;
/// Default time-to-live for addresses discovered through Kademlia.
/// After this time has elapsed and no connection has succeeded, the address will be removed.
const KADEMLIA_DISCOVERY_EXPIRATION: Duration = Duration::from_secs(2 * 3600);
/// After a successful connection, the TTL is set to a minimum at this amount.
const EXPIRATION_PUSH_BACK_CONNEC: Duration = Duration::from_secs(2 * 3600);
/// Initial score that a bootstrap node receives when registered.
const BOOTSTRAP_NODE_SCORE: u32 = 100;
/// Time to live of a boostrap node. This only applies if you start the node later *without*
/// that bootstrap node configured anymore.
const BOOTSTRAP_NODE_EXPIRATION: Duration = Duration::from_secs(24 * 3600);
/// The first time we fail to connect to an address, wait this duration before trying again.
const FIRST_CONNECT_FAIL_BACKOFF: Duration = Duration::from_secs(2);
/// Every time we fail to connect to an address, multiply the backoff by this constant.
const FAIL_BACKOFF_MULTIPLIER: u32 = 2;
/// We need a maximum value for the backoff, overwise we risk an overflow.
const MAX_BACKOFF: Duration = Duration::from_secs(30 * 60);
/// Stores information about the topology of the network.
#[derive(Debug)]
pub struct NetTopology {
/// The actual storage. Never contains a key for `local_peer_id`.
store: FnvHashMap<PeerId, PeerInfo>,
/// Optional path to the file that caches the serialized version of `store`.
cache_path: Option<PathBuf>,
/// PeerId of the local node.
local_peer_id: PeerId,
}
impl NetTopology {
/// Initializes a new `NetTopology` that isn't tied to any file.
///
/// `flush_to_disk()` will be a no-op.
#[inline]
pub fn memory(local_peer_id: PeerId) -> NetTopology {
NetTopology {
store: Default::default(),
cache_path: None,
local_peer_id,
}
}
/// Builds a `NetTopology` that will use `path` as a cache.
///
/// This function tries to load a known topology from the file. If the file doesn't exist
/// or contains garbage data, the execution still continues.
///
/// Calling `flush_to_disk()` in the future writes to the given path.
pub fn from_file<P: AsRef<Path>>(local_peer_id: PeerId, path: P) -> NetTopology {
let path = path.as_ref();
debug!(target: "sub-libp2p", "Initializing peer store for JSON file {:?}", path);
let store = try_load(path, &local_peer_id);
NetTopology {
store,
cache_path: Some(path.to_owned()),
local_peer_id,
}
}
/// Writes the topology into the path passed to `from_file`.
///
/// No-op if the object was created with `memory()`.
pub fn flush_to_disk(&mut self) -> Result<(), IoError> {
let path = match self.cache_path {
Some(ref p) => p,
None => return Ok(())
};
let file = fs::File::create(path)?;
// TODO: the capacity of the BufWriter is kind of arbitrary ; decide better
serialize(BufWriter::with_capacity(1024 * 1024, file), &mut self.store)
}
/// Returns the number of peers in the topology, excluding the local peer.
#[inline]
pub fn num_peers(&self) -> usize {
self.store.len()
}
/// Perform a cleanup pass, removing all obsolete addresses and peers.
///
/// This should be done from time to time.
pub fn cleanup(&mut self) {
let now_systime = SystemTime::now();
self.store.retain(|_, peer| {
let new_addrs = peer.addrs
.drain(..)
.filter(|a| a.expires > now_systime || a.is_connected())
.collect();
peer.addrs = new_addrs;
!peer.addrs.is_empty()
});
}
/// Returns a list of all the known addresses of peers, ordered by the
/// order in which we should attempt to connect to them.
///
/// Because of expiration and back-off mechanisms, this list can grow
/// by itself over time. The `Instant` that is returned corresponds to
/// the earlier known time when a new entry will be added automatically to
/// the list.
pub fn addrs_to_attempt(&mut self) -> (impl Iterator<Item = (&PeerId, &Multiaddr)>, Instant) {
// TODO: optimize
let now = Instant::now();
let now_systime = SystemTime::now();
let mut instant = now + Duration::from_secs(3600);
let mut addrs_out = Vec::new();
let mut peer_addrs = Vec::new();
'peer_loop: for (peer, info) in &mut self.store {
peer_addrs.clear();
for addr in &mut info.addrs {
let (score, is_connected) = addr.score_and_is_connected();
if is_connected {
continue 'peer_loop
}
if score == 0 || addr.expires < now_systime {
continue
}
if addr.back_off_until > now {
instant = cmp::min(instant, addr.back_off_until);
continue
}
peer_addrs.push(((peer, &addr.addr), score));
}
for val in peer_addrs.drain(..) {
addrs_out.push(val);
}
}
addrs_out.sort_by(|a, b| b.1.cmp(&a.1));
(addrs_out.into_iter().map(|a| a.0), instant)
}
/// Adds an address corresponding to a boostrap node.
///
/// We assume that the address is valid, so its score starts very high.
pub fn add_bootstrap_addr(&mut self, peer: &PeerId, addr: Multiaddr) {
if *peer == self.local_peer_id {
return
}
let now_systime = SystemTime::now();
let now = Instant::now();
let peer = peer_access(&mut self.store, peer);
let mut found = false;
let new_addrs = peer.addrs
.drain(..)
.filter_map(|a| {
if a.expires < now_systime && !a.is_connected() {
return None
}
if a.addr == addr {
found = true;
}
Some(a)
})
.collect();
peer.addrs = new_addrs;
if !found {
peer.addrs.push(Addr {
addr,
expires: now_systime + BOOTSTRAP_NODE_EXPIRATION,
back_off_until: now,
next_back_off: FIRST_CONNECT_FAIL_BACKOFF,
score: AddrScore {
connected_since: None,
score: BOOTSTRAP_NODE_SCORE,
latest_score_update: now,
},
});
}
}
/// Indicates the topology that we have discovered new addresses for a given node.
///
/// Returns `true` if the topology has changed in some way. Returns `false` if calling this
/// method was a no-op.
pub fn add_discovered_addrs<I>(
&mut self,
peer_id: &PeerId,
addrs: I,
) -> bool
where I: Iterator<Item = (Multiaddr, bool)> {
if *peer_id == self.local_peer_id {
return false
}
let mut addrs: Vec<_> = addrs.collect();
if addrs.len() > 40 {
warn!(target: "sub-libp2p", "Attempt to add more than 40 addresses for {:?}", peer_id);
addrs.truncate(40);
}
let now_systime = SystemTime::now();
let now = Instant::now();
let peer = peer_access(&mut self.store, peer_id);
let new_addrs = peer.addrs
.drain(..)
.filter(|a| {
if a.expires < now_systime && !a.is_connected() {
return false
}
addrs.retain(|(addr, _)| *addr != a.addr);
true
})
.collect();
peer.addrs = new_addrs;
let mut anything_changed = false;
if !addrs.is_empty() {
anything_changed = true;
trace!(
target: "sub-libp2p",
"Peer store: adding addresses {:?} for {:?}",
addrs,
peer_id,
);
}
'addrs_inserter: for (addr, connectable) in addrs {
let initial_score = if connectable {
DISCOVERY_INITIAL_SCORE_CONNECTABLE
} else {
DISCOVERY_INITIAL_SCORE
};
// Enforce `MAX_ADDRESSES_PER_PEER` before inserting, or skip this entry.
while peer.addrs.len() >= MAX_ADDRESSES_PER_PEER {
let pos = peer.addrs.iter_mut().position(|addr| addr.score() <= initial_score);
if let Some(pos) = pos {
let _ = peer.addrs.remove(pos);
} else {
continue 'addrs_inserter;
}
}
// `addrs` can contain duplicates, therefore we would insert the same address twice.
if peer.addrs.iter().any(|a| a.addr == addr) {
continue;
}
peer.addrs.push(Addr {
addr,
expires: now_systime + KADEMLIA_DISCOVERY_EXPIRATION,
back_off_until: now,
next_back_off: FIRST_CONNECT_FAIL_BACKOFF,
score: AddrScore {
connected_since: None,
score: initial_score,
latest_score_update: now,
},
});
}
anything_changed
}
/// Returns the list of peers that are stored in the topology.
#[inline]
pub fn known_peers(&self) -> impl Iterator<Item = &PeerId> {
self.store.keys()
}
/// Returns the addresses stored for a specific peer, and their reputation score.
///
/// If `include_expired` is true, includes expired addresses that shouldn't be taken into
/// account when dialing.
#[inline]
pub fn addresses_of_peer(&mut self, peer: &PeerId, include_expired: bool)
-> impl Iterator<Item = (&Multiaddr, u32)> {
let now_st = SystemTime::now();
let now_is = Instant::now();
let mut list = self.store.get_mut(peer).into_iter().flat_map(|p| p.addrs.iter_mut()).filter_map(move |addr| {
let (score, connected) = addr.score_and_is_connected();
if include_expired || (addr.expires >= now_st && score > 0 && addr.back_off_until < now_is) || connected {
Some((score, &addr.addr))
} else {
None
}
}).collect::<Vec<_>>();
list.sort_by(|a, b| a.0.cmp(&b.0));
// TODO: meh, optimize
list.into_iter().map(|(score, addr)| (addr, score))
}
/// Marks the given peer as connected through the given endpoint.
pub fn set_connected(&mut self, peer: &PeerId, endpoint: &ConnectedPoint) {
if *peer == self.local_peer_id {
return
}
let addr = match endpoint {
ConnectedPoint::Dialer { address } => address,
ConnectedPoint::Listener { .. } => return
};
let now = Instant::now();
// Just making sure that we have an entry for this peer in `store`, but don't use it.
let _ = peer_access(&mut self.store, peer);
for (peer_in_store, info_in_store) in self.store.iter_mut() {
if peer == peer_in_store {
if let Some(addr) = info_in_store.addrs.iter_mut().find(|a| &a.addr == addr) {
addr.connected_now(CONNECTED_MINIMUM_SCORE);
addr.back_off_until = now;
addr.next_back_off = FIRST_CONNECT_FAIL_BACKOFF;
continue
}
info_in_store.addrs.push(Addr {
addr: addr.clone(),
expires: SystemTime::now() + EXPIRATION_PUSH_BACK_CONNEC,
back_off_until: now,
next_back_off: FIRST_CONNECT_FAIL_BACKOFF,
score: AddrScore {
connected_since: Some(now),
latest_score_update: now,
score: CONNECTED_MINIMUM_SCORE,
},
});
} else {
// Set the score to 0 for any address that matches the one we connected to.
for addr_in_store in &mut info_in_store.addrs {
if &addr_in_store.addr == addr {
addr_in_store.adjust_score(-(MAX_SCORE as i32));
}
}
}
}
}
/// Marks the given peer as disconnected. The endpoint is the one we were connected to.
pub fn set_disconnected(&mut self, _: &PeerId, endpoint: &ConnectedPoint) {
let addr = match endpoint {
ConnectedPoint::Dialer { address } => address,
ConnectedPoint::Listener { .. } => return
};
// Note that we used to have different score values here in the past, but there really
// isn't much point in doing so in practice.
let score_diff = -3;
for info in self.store.values_mut() {
for a in info.addrs.iter_mut() {
if &a.addr == addr {
a.disconnected_now(score_diff);
a.back_off_until = Instant::now() + a.next_back_off;
a.next_back_off = cmp::min(a.next_back_off * FAIL_BACKOFF_MULTIPLIER, MAX_BACKOFF);
let expires_push_back = SystemTime::now() + EXPIRATION_PUSH_BACK_CONNEC;
if a.expires < expires_push_back {
a.expires = expires_push_back;
}
return
}
}
}
}
/// Indicates to the topology that we failed to reach a node when dialing the given address.
pub fn set_unreachable(&mut self, addr: &Multiaddr) {
for info in self.store.values_mut() {
for a in info.addrs.iter_mut() {
if &a.addr != addr {
continue
}
// It is possible that we are connected to this address, and that the dial failure
// concerns another peer.
if a.is_connected() {
continue
}
a.adjust_score(SCORE_DIFF_ON_FAILED_TO_CONNECT);
trace!(target: "sub-libp2p", "Back off for {} = {:?}", addr, a.next_back_off);
a.back_off_until = Instant::now() + a.next_back_off;
a.next_back_off = cmp::min(a.next_back_off * FAIL_BACKOFF_MULTIPLIER, MAX_BACKOFF);
}
}
}
}
fn peer_access<'a>(store: &'a mut FnvHashMap<PeerId, PeerInfo>, peer: &PeerId) -> &'a mut PeerInfo {
// TODO: should be optimizable if HashMap gets a better API
store.entry(peer.clone()).or_insert_with(Default::default)
}
#[derive(Debug, Clone, Default)]
struct PeerInfo {
/// Addresses of that peer.
addrs: Vec<Addr>,
}
#[derive(Debug)]
struct Addr {
/// The multiaddress.
addr: Multiaddr,
/// When the address expires.
expires: SystemTime,
next_back_off: Duration,
/// Don't try to connect to this node until `Instant`.
back_off_until: Instant,
score: AddrScore,
}
impl Clone for Addr {
fn clone(&self) -> Addr {
Addr {
addr: self.addr.clone(),
expires: self.expires,
next_back_off: self.next_back_off,
back_off_until: self.back_off_until,
score: self.score.clone(),
}
}
}
#[derive(Debug, Clone)]
struct AddrScore {
/// If connected, contains the moment when we connected. `None` if we're not connected.
connected_since: Option<Instant>,
/// Score of this address. Potentially needs to be updated based on `latest_score_update`.
score: u32,
/// When we last updated the score.
latest_score_update: Instant,
}
impl Addr {
/// Sets the addr to connected. If the score is lower than the given value, raises it to this
/// value.
fn connected_now(&mut self, raise_to_min: u32) {
let now = Instant::now();
Addr::flush(&mut self.score, now);
self.score.connected_since = Some(now);
if self.score.score < raise_to_min {
self.score.score = raise_to_min;
}
}
/// Applies a modification to the score.
fn adjust_score(&mut self, score_diff: i32) {
Addr::flush(&mut self.score, Instant::now());
if score_diff >= 0 {
self.score.score = cmp::min(MAX_SCORE, self.score.score + score_diff as u32);
} else {
self.score.score = self.score.score.saturating_sub(-score_diff as u32);
}
}
/// Sets the addr to disconnected and applies a modification to the score.
fn disconnected_now(&mut self, score_diff: i32) {
Addr::flush(&mut self.score, Instant::now());
self.score.connected_since = None;
if score_diff >= 0 {
self.score.score = cmp::min(MAX_SCORE, self.score.score + score_diff as u32);
} else {
self.score.score = self.score.score.saturating_sub(-score_diff as u32);
}
}
/// Returns true if we are connected to this addr.
fn is_connected(&self) -> bool {
self.score.connected_since.is_some()
}
/// Returns the score, and true if we are connected to this addr.
fn score_and_is_connected(&mut self) -> (u32, bool) {
Addr::flush(&mut self.score, Instant::now());
let is_connected = self.score.connected_since.is_some();
(self.score.score, is_connected)
}
/// Updates `score` and `latest_score_update`, and returns the score.
fn score(&mut self) -> u32 {
Addr::flush(&mut self.score, Instant::now());
self.score.score
}
fn flush(score: &mut AddrScore, now: Instant) {
if let Some(connected_since) = score.connected_since {
let potential_score: u32 = div_dur_with_dur(now - connected_since, CONNEC_DURATION_PER_SCORE);
// We flush when we connect to an address.
debug_assert!(score.latest_score_update >= connected_since);
let effective_score: u32 =
div_dur_with_dur(score.latest_score_update - connected_since, CONNEC_DURATION_PER_SCORE);
let to_add = potential_score.saturating_sub(effective_score);
score.score = cmp::min(MAX_SCORE, score.score + to_add);
}
score.latest_score_update = now;
}
}
/// Divides a `Duration` with a `Duration`. This exists in the stdlib but isn't stable yet.
// TODO: remove this function once stable
fn div_dur_with_dur(a: Duration, b: Duration) -> u32 {
let a_ms = a.as_secs() * 1_000_000 + u64::from(a.subsec_micros());
let b_ms = b.as_secs() * 1_000_000 + u64::from(b.subsec_micros());
(a_ms / b_ms) as u32
}
/// Serialized version of a `PeerInfo`. Suitable for storage in the cache file.
#[derive(Debug, Clone, Serialize, Deserialize)]
struct SerializedPeerInfo {
addrs: Vec<SerializedAddr>,
}
/// Serialized version of an `Addr`. Suitable for storage in the cache file.
#[derive(Debug, Clone, Serialize, Deserialize)]
struct SerializedAddr {
addr: String,
expires: SystemTime,
score: u32,
}
impl<'a> From<&'a mut Addr> for SerializedAddr {
fn from(addr: &'a mut Addr) -> SerializedAddr {
SerializedAddr {
addr: addr.addr.to_string(),
expires: addr.expires,
score: addr.score(),
}
}
}
/// Attempts to load storage from a file.
/// Ignores any entry equal to `local_peer_id`.
/// Deletes the file and returns an empty map if the file doesn't exist, cannot be opened
/// or is corrupted.
fn try_load(path: impl AsRef<Path>, local_peer_id: &PeerId) -> FnvHashMap<PeerId, PeerInfo> {
let path = path.as_ref();
if !path.exists() {
debug!(target: "sub-libp2p", "Peer storage file {:?} doesn't exist", path);
return Default::default()
}
let mut file = match fs::File::open(path) {
// TODO: the capacity of the BufReader is kind of arbitrary ; decide better
Ok(f) => BufReader::with_capacity(1024 * 1024, f),
Err(err) => {
warn!(target: "sub-libp2p", "Failed to open peer storage file: {:?}", err);
info!(target: "sub-libp2p", "Deleting peer storage file {:?}", path);
let _ = fs::remove_file(path);
return Default::default()
}
};
// We want to support empty files (and treat them as an empty recordset). Unfortunately
// `serde_json` will always produce an error if we do this ("unexpected EOF at line 0
// column 0"). Therefore we start by reading one byte from the file in order to check
// for EOF.
let mut first_byte = [0];
let num_read = match file.read(&mut first_byte) {
Ok(f) => f,
Err(err) => {
// TODO: DRY
warn!(target: "sub-libp2p", "Failed to read peer storage file: {:?}", err);
info!(target: "sub-libp2p", "Deleting peer storage file {:?}", path);
let _ = fs::remove_file(path);
return Default::default()
}
};
if num_read == 0 {
// File is empty.
debug!(target: "sub-libp2p", "Peer storage file {:?} is empty", path);
Default::default()
} else {
let data = Cursor::new(first_byte).chain(file);
match serde_json::from_reader::<_, serde_json::Value>(data) {
Ok(serde_json::Value::Null) => Default::default(),
Ok(serde_json::Value::Object(map)) =>
deserialize_tolerant(map.into_iter(), local_peer_id),
Ok(_) | Err(_) => {
// The `Ok(_)` case means that the file doesn't contain a map.
let _ = fs::remove_file(path);
Default::default()
},
}
}
}
/// Attempts to turn a deserialized version of the storage into the final version.
///
/// Skips entries that are invalid or equal to `local_peer_id`.
fn deserialize_tolerant(
iter: impl Iterator<Item = (String, serde_json::Value)>,
local_peer_id: &PeerId
) -> FnvHashMap<PeerId, PeerInfo> {
let now = Instant::now();
let now_systime = SystemTime::now();
let mut out = FnvHashMap::default();
for (peer, info) in iter {
let peer: PeerId = match peer.parse() {
Ok(p) => p,
Err(_) => continue,
};
if &peer == local_peer_id {
continue
}
let info: SerializedPeerInfo = match serde_json::from_value(info) {
Ok(i) => i,
Err(_) => continue,
};
let mut addrs = Vec::with_capacity(info.addrs.len());
for addr in info.addrs {
let multiaddr = match addr.addr.parse() {
Ok(a) => a,
Err(_) => continue,
};
if addr.expires < now_systime {
continue
}
addrs.push(Addr {
addr: multiaddr,
expires: addr.expires,
next_back_off: FIRST_CONNECT_FAIL_BACKOFF,
back_off_until: now,
score: AddrScore {
connected_since: None,
score: addr.score,
latest_score_update: now,
},
});
}
if addrs.is_empty() {
continue
}
out.insert(peer, PeerInfo { addrs });
}
out
}
/// Attempts to turn a deserialized version of the storage into the final version.
///
/// Skips entries that are invalid or expired.
fn serialize<W: Write>(out: W, map: &mut FnvHashMap<PeerId, PeerInfo>) -> Result<(), IoError> {
let now = SystemTime::now();
let array: FnvHashMap<_, _> = map.iter_mut().filter_map(|(peer, info)| {
if info.addrs.is_empty() {
return None
}
let peer = peer.to_base58();
let info = SerializedPeerInfo {
addrs: info.addrs.iter_mut()
.filter_map(|a| if a.expires > now || a.is_connected() {
Some(a.into())
} else {
None
})
.collect(),
};
Some((peer, info))
}).collect();
serde_json::to_writer_pretty(out, &array)
.map_err(|err| IoError::new(IoErrorKind::Other, err))
}
@@ -16,7 +16,7 @@
use crate::ProtocolId;
use bytes::Bytes;
use libp2p::core::{Endpoint, UpgradeInfo, InboundUpgrade, OutboundUpgrade, upgrade::ProtocolName};
use libp2p::core::{Negotiated, Endpoint, UpgradeInfo, InboundUpgrade, OutboundUpgrade, upgrade::ProtocolName};
use libp2p::tokio_codec::Framed;
use log::warn;
use std::{collections::VecDeque, io, iter, marker::PhantomData, vec::IntoIter as VecIntoIter};
@@ -92,7 +92,7 @@ pub struct RegisteredProtocolSubstream<TMessage, TSubstream> {
/// If true, we should call `poll_complete` on the inner sink.
requires_poll_complete: bool,
/// The underlying substream.
inner: stream::Fuse<Framed<TSubstream, UviBytes<Vec<u8>>>>,
inner: stream::Fuse<Framed<Negotiated<TSubstream>, UviBytes<Vec<u8>>>>,
/// Id of the protocol.
protocol_id: ProtocolId,
/// Version of the protocol that was negotiated.
@@ -385,7 +385,7 @@ where TSubstream: AsyncRead + AsyncWrite,
fn upgrade_inbound(
self,
socket: TSubstream,
socket: Negotiated<TSubstream>,
info: Self::Info,
) -> Self::Future {
let framed = {
@@ -418,7 +418,7 @@ where TSubstream: AsyncRead + AsyncWrite,
fn upgrade_outbound(
self,
socket: TSubstream,
socket: Negotiated<TSubstream>,
info: Self::Info,
) -> Self::Future {
let framed = Framed::new(socket, UviBytes::default());
+4 -10
View File
@@ -106,12 +106,6 @@ pub struct NetworkState {
/// List of addresses the node is currently listening on.
pub listened_addresses: HashSet<Multiaddr>,
// TODO (https://github.com/libp2p/rust-libp2p/issues/978): external_addresses: Vec<Multiaddr>,
/// If true, we only accept reserved peers.
pub is_reserved_only: bool,
/// PeerIds of the nodes that are marked as reserved.
pub reserved_peers: HashSet<String>,
/// PeerIds of the nodes that are banned, and how long in the seconds the ban remains.
pub banned_peers: HashMap<String, u64>,
/// List of node we're connected to.
pub connected_peers: HashMap<String, NetworkStatePeer>,
/// List of node that we know of but that we're not connected to.
@@ -137,15 +131,15 @@ pub struct NetworkStatePeer {
/// If true, the peer is "open", which means that we have a Substrate-related protocol
/// with this peer.
pub open: bool,
/// List of addresses known for this node, with its reputation score.
pub known_addresses: HashMap<Multiaddr, u32>,
/// List of addresses known for this node.
pub known_addresses: HashSet<Multiaddr>,
}
#[derive(Debug, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct NetworkStateNotConnectedPeer {
/// List of addresses known for this node, with its reputation score.
pub known_addresses: HashMap<Multiaddr, u32>,
/// List of addresses known for this node.
pub known_addresses: HashSet<Multiaddr>,
}
#[derive(Debug, PartialEq, Serialize)]
+56 -128
View File
@@ -19,20 +19,19 @@ use crate::{
transport, NetworkState, NetworkStatePeer, NetworkStateNotConnectedPeer
};
use crate::custom_proto::{CustomMessage, RegisteredProtocol};
use crate::{NetworkConfiguration, NodeIndex, parse_str_addr};
use crate::{NetworkConfiguration, NonReservedPeerMode, NodeIndex, parse_str_addr};
use fnv::FnvHashMap;
use futures::{prelude::*, Stream};
use libp2p::{multiaddr::Protocol, Multiaddr, PeerId};
use libp2p::{multiaddr::Protocol, Multiaddr, core::swarm::NetworkBehaviour, PeerId};
use libp2p::core::{Swarm, nodes::Substream, transport::boxed::Boxed, muxing::StreamMuxerBox};
use libp2p::core::nodes::ConnectedPoint;
use log::{debug, error, info, warn};
use std::collections::hash_map::Entry;
use std::fs;
use std::io::{Error as IoError, ErrorKind as IoErrorKind};
use std::io::Error as IoError;
use std::path::Path;
use std::sync::Arc;
use std::time::{Duration, Instant};
use tokio_timer::Interval;
use std::time::Duration;
/// Starts the substrate libp2p service.
///
@@ -40,13 +39,48 @@ use tokio_timer::Interval;
pub fn start_service<TMessage>(
config: NetworkConfiguration,
registered_custom: RegisteredProtocol<TMessage>,
) -> Result<Service<TMessage>, IoError>
) -> Result<(Service<TMessage>, Arc<substrate_peerset::Peerset>), IoError>
where TMessage: CustomMessage + Send + 'static {
if let Some(ref path) = config.net_config_path {
fs::create_dir_all(Path::new(path))?;
}
// List of multiaddresses that we know in the network.
let mut known_addresses = Vec::new();
let mut bootnodes = Vec::new();
let mut reserved_nodes = Vec::new();
// Process the bootnodes.
for bootnode in config.boot_nodes.iter() {
match parse_str_addr(bootnode) {
Ok((peer_id, addr)) => {
bootnodes.push(peer_id.clone());
known_addresses.push((peer_id, addr));
},
Err(_) => warn!(target: "sub-libp2p", "Not a valid bootnode address: {}", bootnode),
}
}
// Initialize the reserved peers.
for reserved in config.reserved_nodes.iter() {
if let Ok((peer_id, addr)) = parse_str_addr(reserved) {
reserved_nodes.push(peer_id.clone());
known_addresses.push((peer_id, addr));
} else {
warn!(target: "sub-libp2p", "Not a valid reserved node address: {}", reserved);
}
}
// Build the peerset.
let (peerset, peerset_receiver) = substrate_peerset::Peerset::from_config(substrate_peerset::PeersetConfig {
in_peers: 25,
out_peers: 25,
bootnodes,
reserved_only: config.non_reserved_mode == NonReservedPeerMode::Deny,
reserved_nodes,
});
// Private and public keys configuration.
let local_identity = config.node_key.clone().into_keypair()?;
let local_public = local_identity.public();
@@ -54,7 +88,8 @@ where TMessage: CustomMessage + Send + 'static {
// Build the swarm.
let (mut swarm, bandwidth) = {
let behaviour = Behaviour::new(&config, local_public, registered_custom);
let user_agent = format!("{} ({})", config.client_version, config.node_name);
let behaviour = Behaviour::new(user_agent, local_public, registered_custom, known_addresses, peerset_receiver);
let (transport, bandwidth) = transport::build_transport(local_identity);
(Swarm::new(transport, behaviour, local_peer_id.clone()), bandwidth)
};
@@ -75,36 +110,16 @@ where TMessage: CustomMessage + Send + 'static {
Swarm::add_external_address(&mut swarm, addr.clone());
}
// Connect to the bootnodes.
for bootnode in config.boot_nodes.iter() {
match parse_str_addr(bootnode) {
Ok((peer_id, _)) => Swarm::dial(&mut swarm, peer_id),
Err(_) => warn!(target: "sub-libp2p", "Not a valid bootnode address: {}", bootnode),
}
}
// Initialize the reserved peers.
for reserved in config.reserved_nodes.iter() {
if let Ok((peer_id, addr)) = parse_str_addr(reserved) {
swarm.add_reserved_peer(peer_id.clone(), addr);
Swarm::dial(&mut swarm, peer_id);
} else {
warn!(target: "sub-libp2p", "Not a valid reserved node address: {}", reserved);
}
}
debug!(target: "sub-libp2p", "Topology started with {} entries",
swarm.num_topology_peers());
Ok(Service {
let service = Service {
swarm,
bandwidth,
nodes_info: Default::default(),
index_by_id: Default::default(),
next_node_id: 1,
cleanup: Interval::new_interval(Duration::from_secs(60)),
injected_events: Vec::new(),
})
};
Ok((service, peerset))
}
/// Event produced by the service.
@@ -164,10 +179,6 @@ pub struct Service<TMessage> where TMessage: CustomMessage {
/// Next index to assign to a node.
next_node_id: NodeIndex,
/// Stream that fires when we need to cleanup and flush the topology, and cleanup the disabled
/// peers.
cleanup: Interval,
/// Events to produce on the Stream.
injected_events: Vec<ServiceEvent<TMessage>>,
}
@@ -189,13 +200,11 @@ impl<TMessage> Service<TMessage>
where TMessage: CustomMessage + Send + 'static {
/// Returns a struct containing tons of useful information about the network.
pub fn state(&mut self) -> NetworkState {
let now = Instant::now();
let connected_peers = {
let swarm = &mut self.swarm;
self.nodes_info.values().map(move |info| {
let known_addresses = swarm.known_addresses(&info.peer_id)
.map(|(a, s)| (a.clone(), s)).collect();
let known_addresses = NetworkBehaviour::addresses_of_peer(&mut **swarm, &info.peer_id)
.into_iter().collect();
(info.peer_id.to_base58(), NetworkStatePeer {
endpoint: info.endpoint.clone().into(),
@@ -214,10 +223,9 @@ where TMessage: CustomMessage + Send + 'static {
let list = swarm.known_peers().filter(|p| !index_by_id.contains_key(p))
.cloned().collect::<Vec<_>>();
list.into_iter().map(move |peer_id| {
let known_addresses = swarm.known_addresses(&peer_id)
.map(|(a, s)| (a.clone(), s)).collect();
(peer_id.to_base58(), NetworkStateNotConnectedPeer {
known_addresses,
known_addresses: NetworkBehaviour::addresses_of_peer(&mut **swarm, &peer_id)
.into_iter().collect(),
})
}).collect()
};
@@ -225,12 +233,6 @@ where TMessage: CustomMessage + Send + 'static {
NetworkState {
peer_id: Swarm::local_peer_id(&self.swarm).to_base58(),
listened_addresses: Swarm::listeners(&self.swarm).cloned().collect(),
reserved_peers: self.swarm.reserved_peers().map(|p| p.to_base58()).collect(),
banned_peers: self.swarm.banned_nodes().map(|(p, until)| {
let dur = if until > now { until - now } else { Duration::new(0, 0) };
(p.to_base58(), dur.as_secs())
}).collect(),
is_reserved_only: self.swarm.is_reserved_only(),
average_download_per_sec: self.bandwidth.average_download_per_sec(),
average_upload_per_sec: self.bandwidth.average_upload_per_sec(),
connected_peers,
@@ -268,31 +270,6 @@ where TMessage: CustomMessage + Send + 'static {
self.nodes_info.keys().cloned()
}
/// Try to add a reserved peer.
pub fn add_reserved_peer(&mut self, peer_id: PeerId, addr: Multiaddr) {
self.swarm.add_reserved_peer(peer_id, addr);
}
/// Try to remove a reserved peer.
///
/// If we are in reserved mode and we were connected to a node with this peer ID, then this
/// method will disconnect it.
pub fn remove_reserved_peer(&mut self, peer_id: PeerId) {
self.swarm.remove_reserved_peer(peer_id);
}
/// Start accepting all peers again if we weren't.
#[inline]
pub fn accept_unreserved_peers(&mut self) {
self.swarm.accept_unreserved_peers();
}
/// Start refusing non-reserved nodes. Disconnects the nodes that we are connected to that
/// aren't reserved.
pub fn deny_unreserved_peers(&mut self) {
self.swarm.deny_unreserved_peers();
}
/// Returns the `PeerId` of a node.
#[inline]
pub fn peer_id_of_node(&self, node_index: NodeIndex) -> Option<&PeerId> {
@@ -327,23 +304,10 @@ where TMessage: CustomMessage + Send + 'static {
}
}
/// Disconnects a peer and bans it for a little while.
///
/// Same as `drop_node`, except that the same peer will not be able to reconnect later.
#[inline]
pub fn ban_node(&mut self, node_index: NodeIndex) {
if let Some(info) = self.nodes_info.get(&node_index) {
info!(target: "sub-libp2p", "Banned {:?} (#{:?}, {:?}, {:?})", info.peer_id,
node_index, info.endpoint, info.client_version);
self.swarm.ban_node(info.peer_id.clone());
}
}
/// Disconnects a peer.
///
/// This is asynchronous and will not immediately close the peer.
/// Corresponding closing events will be generated once the closing actually happens.
#[inline]
pub fn drop_node(&mut self, node_index: NodeIndex) {
if let Some(info) = self.nodes_info.get(&node_index) {
debug!(target: "sub-libp2p", "Dropping {:?} on purpose (#{:?}, {:?}, {:?})",
@@ -352,6 +316,11 @@ where TMessage: CustomMessage + Send + 'static {
}
}
/// Adds a hard-coded address for the given peer, that never expires.
pub fn add_known_address(&mut self, peer_id: PeerId, addr: Multiaddr) {
self.swarm.add_known_address(peer_id, addr)
}
/// Get debug info for a given peer.
pub fn peer_debug_info(&self, who: NodeIndex) -> String {
if let Some(info) = self.nodes_info.get(&who) {
@@ -394,7 +363,6 @@ where TMessage: CustomMessage + Send + 'static {
loop {
match self.swarm.poll() {
Ok(Async::Ready(Some(BehaviourOut::CustomProtocolOpen { peer_id, version, endpoint }))) => {
debug!(target: "sub-libp2p", "Opened custom protocol with {:?}", peer_id);
let node_index = self.index_of_peer_or_assign(peer_id.clone(), endpoint);
break Ok(Async::Ready(Some(ServiceEvent::OpenedCustomProtocol {
peer_id,
@@ -403,8 +371,7 @@ where TMessage: CustomMessage + Send + 'static {
debug_info: self.peer_debug_info(node_index),
})))
}
Ok(Async::Ready(Some(BehaviourOut::CustomProtocolClosed { peer_id, result }))) => {
debug!(target: "sub-libp2p", "Custom protocol with {:?} closed: {:?}", peer_id, result);
Ok(Async::Ready(Some(BehaviourOut::CustomProtocolClosed { peer_id, .. }))) => {
let node_index = *self.index_by_id.get(&peer_id).expect("index_by_id is always kept in sync with the state of the behaviour");
break Ok(Async::Ready(Some(ServiceEvent::ClosedCustomProtocol {
node_index,
@@ -457,40 +424,6 @@ where TMessage: CustomMessage + Send + 'static {
}
}
}
/// Polls the stream that fires when we need to cleanup and flush the topology.
fn poll_cleanup(&mut self) -> Poll<Option<ServiceEvent<TMessage>>, IoError> {
loop {
match self.cleanup.poll() {
Ok(Async::NotReady) => return Ok(Async::NotReady),
Ok(Async::Ready(Some(_))) => {
debug!(target: "sub-libp2p", "Cleaning and flushing topology");
self.swarm.cleanup();
if let Err(err) = self.swarm.flush_topology() {
warn!(target: "sub-libp2p", "Failed to flush topology: {:?}", err);
}
debug!(target: "sub-libp2p", "Topology now contains {} nodes",
self.swarm.num_topology_peers());
}
Ok(Async::Ready(None)) => {
warn!(target: "sub-libp2p", "Topology flush stream ended unexpectedly");
return Ok(Async::Ready(None))
}
Err(err) => {
warn!(target: "sub-libp2p", "Topology flush stream errored: {:?}", err);
return Err(IoError::new(IoErrorKind::Other, err))
}
}
}
}
}
impl<TMessage> Drop for Service<TMessage> where TMessage: CustomMessage {
fn drop(&mut self) {
if let Err(err) = self.swarm.flush_topology() {
warn!(target: "sub-libp2p", "Failed to flush topology: {:?}", err);
}
}
}
impl<TMessage> Stream for Service<TMessage> where TMessage: CustomMessage + Send + 'static {
@@ -507,11 +440,6 @@ impl<TMessage> Stream for Service<TMessage> where TMessage: CustomMessage + Send
Async::NotReady => (),
}
match self.poll_cleanup()? {
Async::Ready(value) => return Ok(Async::Ready(value)),
Async::NotReady => (),
}
// The only way we reach this is if we went through all the `NotReady` paths above,
// ensuring the current task is registered everywhere.
Ok(Async::NotReady)
+1 -1
View File
@@ -41,7 +41,7 @@ fn build_nodes<TMsg>(num: usize) -> Vec<substrate_network_libp2p::Service<TMsg>>
};
let proto = substrate_network_libp2p::RegisteredProtocol::new(*b"tst", &[1]);
result.push(substrate_network_libp2p::start_service(config, proto).unwrap());
result.push(substrate_network_libp2p::start_service(config, proto).unwrap().0);
}
result
+1
View File
@@ -27,6 +27,7 @@ client = { package = "substrate-client", path = "../../core/client" }
runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives" }
parity-codec = { version = "3.2", features = ["derive"] }
network_libp2p = { package = "substrate-network-libp2p", path = "../../core/network-libp2p" }
peerset = { package = "substrate-peerset", path = "../../core/peerset" }
tokio = "0.1.11"
keyring = { package = "substrate-keyring", path = "../../core/keyring", optional = true }
test_client = { package = "substrate-test-client", path = "../../core/test-client", optional = true }
+19 -11
View File
@@ -24,6 +24,7 @@ use parking_lot::{Mutex, RwLock};
use network_libp2p::{ProtocolId, NetworkConfiguration, NodeIndex, Severity};
use network_libp2p::{start_service, parse_str_addr, Service as NetworkService, ServiceEvent as NetworkServiceEvent};
use network_libp2p::{multiaddr, RegisteredProtocol, NetworkState};
use peerset::Peerset;
use consensus::import_queue::{ImportQueue, Link};
use crate::consensus_gossip::ConsensusGossip;
use crate::message::{Message, ConsensusEngineId};
@@ -138,6 +139,9 @@ pub struct Service<B: BlockT + 'static, S: NetworkSpecialization<B>> {
peers: Arc<RwLock<HashMap<NodeIndex, ConnectedPeer<B>>>>,
/// Network service
network: Arc<Mutex<NetworkService<Message<B>>>>,
/// Peerset manager (PSM); manages the reputation of nodes and indicates the network which
/// nodes it should be connected to or not.
peerset: Arc<Peerset>,
/// Protocol sender
protocol_sender: Sender<ProtocolMsg<B, S>>,
/// Sender for messages to the background service task, and handle for the background thread.
@@ -174,7 +178,7 @@ impl<B: BlockT + 'static, S: NetworkSpecialization<B>> Service<B, S> {
)?;
let versions = [(protocol::CURRENT_VERSION as u8)];
let registered = RegisteredProtocol::new(protocol_id, &versions[..]);
let (thread, network) = start_thread(
let (thread, network, peerset) = start_thread(
network_to_protocol_sender,
network_port,
params.network_config,
@@ -186,6 +190,7 @@ impl<B: BlockT + 'static, S: NetworkSpecialization<B>> Service<B, S> {
is_offline,
is_major_syncing,
peers,
peerset,
network,
protocol_sender: protocol_sender.clone(),
bg_thread: Some(thread),
@@ -343,20 +348,21 @@ pub trait ManageNetwork {
impl<B: BlockT + 'static, S: NetworkSpecialization<B>> ManageNetwork for Service<B, S> {
fn accept_unreserved_peers(&self) {
self.network.lock().accept_unreserved_peers();
self.peerset.set_reserved_only(false);
}
fn deny_unreserved_peers(&self) {
self.network.lock().deny_unreserved_peers();
self.peerset.set_reserved_only(true);
}
fn remove_reserved_peer(&self, peer: PeerId) {
self.network.lock().remove_reserved_peer(peer);
self.peerset.remove_reserved_peer(&peer);
}
fn add_reserved_peer(&self, peer: String) -> Result<(), String> {
let (addr, peer_id) = parse_str_addr(&peer).map_err(|e| format!("{:?}", e))?;
self.network.lock().add_reserved_peer(addr, peer_id);
let (peer_id, addr) = parse_str_addr(&peer).map_err(|e| format!("{:?}", e))?;
self.peerset.add_reserved_peer(peer_id.clone());
self.network.lock().add_known_address(peer_id, addr);
Ok(())
}
@@ -466,10 +472,10 @@ fn start_thread<B: BlockT + 'static>(
network_port: NetworkPort<B>,
config: NetworkConfiguration,
registered: RegisteredProtocol<Message<B>>,
) -> Result<((oneshot::Sender<()>, thread::JoinHandle<()>), Arc<Mutex<NetworkService<Message<B>>>>), Error> {
) -> Result<((oneshot::Sender<()>, thread::JoinHandle<()>), Arc<Mutex<NetworkService<Message<B>>>>, Arc<Peerset>), Error> {
// Start the main service.
let service = match start_service(config, registered) {
Ok(service) => Arc::new(Mutex::new(service)),
let (service, peerset) = match start_service(config, registered) {
Ok((service, peerset)) => (Arc::new(Mutex::new(service)), peerset),
Err(err) => {
warn!("Error starting network: {}", err);
return Err(err.into())
@@ -493,7 +499,7 @@ fn start_thread<B: BlockT + 'static>(
};
})?;
Ok(((close_tx, thread), service))
Ok(((close_tx, thread), service, peerset))
}
/// Runs the background thread that handles the networking.
@@ -530,7 +536,9 @@ fn run_thread<B: BlockT + 'static>(
match severity {
Severity::Bad(message) => {
info!(target: "sync", "Banning {:?} because {:?}", who, message);
network_service_2.lock().ban_node(who)
warn!(target: "sync", "Banning a node is a deprecated mechanism that \
should be removed");
network_service_2.lock().drop_node(who)
},
Severity::Useless(message) => {
info!(target: "sync", "Dropping {:?} because {:?}", who, message);
+20
View File
@@ -0,0 +1,20 @@
[package]
description = "Connectivity manager based on reputation"
homepage = "http://parity.io"
license = "GPL-3.0"
name = "substrate-peerset"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
[dependencies]
fnv = "1.0"
futures = "0.1"
libp2p = { git = "https://github.com/tomaka/libp2p-rs", branch = "substrate-tmp-2019-03-20", default-features = false }
log = "0.4"
parking_lot = "0.7"
rand = "0.6"
serde = "1.0.70"
serde_derive = "1.0.70"
serde_json = "1.0.24"
tokio-io = "0.1"
+297
View File
@@ -0,0 +1,297 @@
// Copyright 2018-2019 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/>.
//! Peer Set Manager (PSM). Contains the strategy for choosing which nodes the network should be
//! connected to.
use std::collections::HashSet;
use futures::{prelude::*, sync::mpsc};
use libp2p::PeerId;
use parking_lot::Mutex;
use std::sync::Arc;
/// Shared part of the peer set manager (PSM). Distributed around the code.
pub struct Peerset {
tx: mpsc::UnboundedSender<Message>,
inner: Mutex<Inner>,
}
struct Inner {
/// List of nodes that we know exist but we are not connected to.
discovered: Vec<PeerId>,
/// List of reserved nodes.
reserved: HashSet<PeerId>,
/// If true, we only accept reserved nodes.
reserved_only: bool,
/// Node slots. Each slot contains either `None` if the node is free, or `Some` if it is
/// assigned to a peer.
slots: Vec<Option<PeerId>>,
}
/// Message that can be sent by the peer set manager (PSM).
#[derive(Debug)]
pub enum Message {
/// Request to open a connection to the given peer. From the point of view of the PSM, we are
/// immediately connected.
Connect(PeerId),
/// Drop the connection to the given peer, or cancel the connection attempt after a `Connect`.
Drop(PeerId),
/// Equivalent to `Connect` for the peer corresponding to this incoming index.
Accept(IncomingIndex),
/// Equivalent to `Drop` for the peer corresponding to this incoming index.
Reject(IncomingIndex),
}
/// Opaque identifier for an incoming connection. Allocated by the network.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct IncomingIndex(pub u64);
impl From<u64> for IncomingIndex {
fn from(val: u64) -> IncomingIndex {
IncomingIndex(val)
}
}
/// Configuration to pass when creating the peer set manager.
#[derive(Debug)]
pub struct PeersetConfig {
/// Maximum number of ingoing links to peers.
pub in_peers: u32,
/// Maximum number of outgoing links to peers.
pub out_peers: u32,
/// List of bootstrap nodes to initialize the peer with.
///
/// > **Note**: Keep in mind that the networking has to know an address for these nodes,
/// > otherwise it will not be able to connect to them.
pub bootnodes: Vec<PeerId>,
/// If true, we only accept reserved nodes.
pub reserved_only: bool,
/// List of nodes that we should always be connected to.
///
/// > **Note**: Keep in mind that the networking has to know an address for these nodes,
/// > otherwise it will not be able to connect to them.
pub reserved_nodes: Vec<PeerId>,
}
/// Side of the peer set manager owned by the network. In other words, the "receiving" side.
///
/// Implements the `Stream` trait and can be polled for messages. The `Stream` never ends and never
/// errors.
pub struct PeersetMut {
parent: Arc<Peerset>,
rx: mpsc::UnboundedReceiver<Message>,
}
impl Peerset {
/// Builds a new peerset from the given configuration.
pub fn from_config(config: PeersetConfig) -> (Arc<Peerset>, PeersetMut) {
let (tx, rx) = mpsc::unbounded();
let mut inner = Inner {
discovered: config.bootnodes.into_iter().collect(),
reserved: Default::default(),
reserved_only: config.reserved_only,
slots: (0 .. (config.in_peers + config.out_peers)).map(|_| None).collect(),
};
alloc_slots(&mut inner, &tx);
let peerset = Arc::new(Peerset {
tx,
inner: Mutex::new(inner),
});
let rx = PeersetMut {
parent: peerset.clone(),
rx,
};
for reserved in config.reserved_nodes {
peerset.add_reserved_peer(reserved);
}
(peerset, rx)
}
/// Adds a new reserved peer. The peerset will make an effort to always remain connected to
/// this peer.
///
/// Has no effect if the node was already a reserved peer.
///
/// > **Note**: Keep in mind that the networking has to know an address for this node,
/// > otherwise it will not be able to connect to it.
pub fn add_reserved_peer(&self, peer_id: PeerId) {
let mut inner = self.inner.lock();
if !inner.reserved.insert(peer_id.clone()) {
// Immediately return if this peer was already in the list.
return;
}
// Assign a slot for this reserved peer.
if let Some(pos) = inner.slots.iter().position(|s| s.as_ref().map(|n| !inner.reserved.contains(n)).unwrap_or(true)) {
let _ = self.tx.unbounded_send(Message::Connect(peer_id.clone()));
inner.slots[pos] = Some(peer_id);
} else {
// All slots are filled with reserved peers.
if inner.discovered.iter().all(|p| *p != peer_id) {
inner.discovered.push(peer_id);
}
}
}
/// Remove a previously-added reserved peer.
///
/// Has no effect if the node was not a reserved peer.
pub fn remove_reserved_peer(&self, peer_id: &PeerId) {
let mut inner = self.inner.lock();
inner.reserved.remove(peer_id);
}
/// Sets whether or not the peerset only has connections .
pub fn set_reserved_only(&self, reserved_only: bool) {
let mut inner = self.inner.lock();
let inner = &mut *inner; // Fixes a borrowing issue.
inner.reserved_only = reserved_only;
// Disconnect non-reserved nodes.
if reserved_only {
for slot in &mut inner.slots {
if let Some(peer) = slot.as_ref() {
if inner.reserved.contains(peer) {
continue;
}
let _ = self.tx.unbounded_send(Message::Drop(peer.clone()));
}
*slot = None;
}
}
}
/// Reports an adjustement to the reputation of the given peer.
pub fn report_peer(&self, _peer_id: &PeerId, _score_diff: i32) {
// This is not implemented in this dummy implementation.
}
}
fn alloc_slots(inner: &mut Inner, tx: &mpsc::UnboundedSender<Message>) {
if inner.reserved_only {
return;
}
for slot in inner.slots.iter_mut() {
if slot.is_some() {
continue;
}
if !inner.discovered.is_empty() {
let elem = inner.discovered.remove(0);
*slot = Some(elem.clone());
let _ = tx.unbounded_send(Message::Connect(elem));
}
}
}
impl PeersetMut {
/// Indicate that we received an incoming connection. Must be answered either with
/// a corresponding `Accept` or `Reject`, except if we were already connected to this peer.
///
/// Note that this mechanism is orthogonal to `Connect`/`Drop`. Accepting an incoming
/// connection implicitely means `Accept`, but incoming connections aren't cancelled by
/// `dropped`.
///
/// Because of concurrency issues, it is acceptable to call `incoming` with a `PeerId` the
/// peerset is already connected to, in which case it must not answer.
pub fn incoming(&self, peer_id: PeerId, index: IncomingIndex) {
let mut inner = self.parent.inner.lock();
if inner.slots.iter().any(|s| s.as_ref() == Some(&peer_id)) {
return
}
if let Some(pos) = inner.slots.iter().position(|s| s.is_none()) {
inner.slots[pos] = Some(peer_id);
let _ = self.parent.tx.unbounded_send(Message::Accept(index));
} else {
if inner.discovered.iter().all(|p| *p != peer_id) {
inner.discovered.push(peer_id);
}
let _ = self.parent.tx.unbounded_send(Message::Reject(index));
}
}
/// Indicate that we dropped an active connection with a peer, or that we failed to connect.
///
/// Must only be called after the PSM has either generated a `Connect` message with this
/// `PeerId`, or accepted an incoming connection with this `PeerId`.
pub fn dropped(&self, peer_id: &PeerId) {
let mut inner = self.parent.inner.lock();
// Automatically connect back if reserved.
if inner.reserved.contains(peer_id) {
let _ = self.parent.tx.unbounded_send(Message::Connect(peer_id.clone()));
return
}
// Otherwise, free the slot.
for slot in inner.slots.iter_mut() {
if slot.as_ref() == Some(peer_id) {
*slot = None;
}
}
// Note: in this dummy implementation we consider that peers never expire. As soon as we
// are disconnected from a peer, we try again.
if inner.discovered.iter().all(|p| p != peer_id) {
inner.discovered.push(peer_id.clone());
}
alloc_slots(&mut inner, &self.parent.tx);
}
/// Adds a discovered peer id to the PSM.
///
/// > **Note**: There is no equivalent "expired" message, meaning that it is the responsibility
/// > of the PSM to remove `PeerId`s that fail to dial too often.
pub fn discovered(&self, peer_id: PeerId) {
let mut inner = self.parent.inner.lock();
if inner.slots.iter().any(|p| p.as_ref() == Some(&peer_id)) {
return;
}
if inner.discovered.iter().all(|p| *p != peer_id) {
inner.discovered.push(peer_id);
}
alloc_slots(&mut inner, &self.parent.tx);
}
}
impl Stream for PeersetMut {
type Item = Message;
type Error = ();
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
self.rx.poll()
}
}
-6
View File
@@ -50,9 +50,6 @@ impl network::SyncProvider<Block> for Status {
network::NetworkState {
peer_id: String::new(),
listened_addresses: Default::default(),
is_reserved_only: false,
reserved_peers: Default::default(),
banned_peers: Default::default(),
connected_peers: Default::default(),
not_connected_peers: Default::default(),
average_download_per_sec: 0,
@@ -207,9 +204,6 @@ fn system_network_state() {
network::NetworkState {
peer_id: String::new(),
listened_addresses: Default::default(),
is_reserved_only: false,
reserved_peers: Default::default(),
banned_peers: Default::default(),
connected_peers: Default::default(),
not_connected_peers: Default::default(),
average_download_per_sec: 0,