From 74a40283b817dab7d319b8c25a3a010c7ac25781 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Tue, 29 Jan 2019 16:58:49 +0100 Subject: [PATCH 01/18] Update libp2p --- Cargo.lock | 384 +++++++++++------- core/keystore/Cargo.toml | 2 +- core/keystore/src/lib.rs | 11 +- core/network-libp2p/Cargo.toml | 2 +- core/network-libp2p/src/behaviour.rs | 70 +++- .../src/custom_proto/behaviour.rs | 92 ++++- .../src/custom_proto/handler.rs | 21 +- core/network-libp2p/src/custom_proto/mod.rs | 1 + .../src/{ => custom_proto}/topology.rs | 103 +---- core/network-libp2p/src/lib.rs | 1 - core/network-libp2p/src/service_task.rs | 46 +-- core/network-libp2p/tests/test.rs | 2 +- core/primitives/Cargo.toml | 2 +- core/primitives/src/ed25519.rs | 12 +- 14 files changed, 428 insertions(+), 321 deletions(-) rename core/network-libp2p/src/{ => custom_proto}/topology.rs (86%) diff --git a/Cargo.lock b/Cargo.lock index 535a77a0568be..9b83987a357e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,33 +10,33 @@ dependencies = [ [[package]] name = "aes-ctr" -version = "0.1.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aes-soft 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aesni 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ctr 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "aes-soft" -version = "0.2.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "aesni" -version = "0.4.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -94,10 +94,19 @@ dependencies = [ [[package]] name = "asn1_der" -version = "0.5.10" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "etrace 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "asn1_der_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "asn1_der_derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +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)", ] [[package]] @@ -251,10 +260,10 @@ dependencies = [ [[package]] name = "block-cipher-trait" -version = "0.5.3" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -467,7 +476,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.3 (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.4 (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)", ] @@ -588,11 +597,11 @@ dependencies = [ [[package]] name = "ctr" -version = "0.1.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -626,6 +635,18 @@ dependencies = [ "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "curve25519-dalek" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 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)", + "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "data-encoding" version = "2.1.2" @@ -725,11 +746,6 @@ dependencies = [ "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "etrace" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "exit-future" version = "0.1.3" @@ -1289,27 +1305,28 @@ dependencies = [ [[package]] name = "libp2p" -version = "0.2.2" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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)", - "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-dns 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-floodsub 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-identify 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-kad 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-mdns 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-mplex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-ping 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-plaintext 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-ratelimit 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-secio 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-tcp 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-uds 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-websocket 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-yamux 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-dns 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-floodsub 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-identify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-kad 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-mdns 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-mplex 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-noise 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-ping 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-plaintext 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-ratelimit 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-secio 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-tcp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-uds 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-websocket 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-yamux 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "stdweb 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1320,7 +1337,7 @@ dependencies = [ [[package]] name = "libp2p-core" -version = "0.2.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1328,23 +1345,24 @@ 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)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multistream-select 0.2.0 (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.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.2.5 (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)", "rw-stream-sink 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.8 (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)", "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-core-derive" -version = "0.2.2" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1353,11 +1371,11 @@ dependencies = [ [[package]] name = "libp2p-dns" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1366,7 +1384,7 @@ dependencies = [ [[package]] name = "libp2p-floodsub" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1374,9 +1392,9 @@ dependencies = [ "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.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.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)", "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1385,17 +1403,17 @@ dependencies = [ [[package]] name = "libp2p-identify" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.2.5 (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)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1406,7 +1424,7 @@ dependencies = [ [[package]] name = "libp2p-kad" -version = "0.2.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1415,15 +1433,15 @@ 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.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-identify 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-ping 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-identify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-ping 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (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)", "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1434,16 +1452,17 @@ dependencies = [ [[package]] name = "libp2p-mdns" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "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.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (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)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1454,13 +1473,13 @@ dependencies = [ [[package]] name = "libp2p-mplex" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "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)", @@ -1468,19 +1487,34 @@ dependencies = [ "unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "libp2p-noise" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +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.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "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)", + "snow 0.5.0 (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 = "libp2p-ping" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.1.0 (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.4 (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)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1489,22 +1523,22 @@ dependencies = [ [[package]] name = "libp2p-plaintext" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-ratelimit" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "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)", @@ -1512,38 +1546,38 @@ dependencies = [ [[package]] name = "libp2p-secio" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aes-ctr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "asn1_der 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "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)", "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "ctr 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "ed25519-dalek 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.13.5 (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.5 (registry+https://github.com/rust-lang/crates.io-index)", "rw-stream-sink 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "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)", - "twofish 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-tcp" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1553,11 +1587,11 @@ dependencies = [ [[package]] name = "libp2p-uds" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1565,11 +1599,11 @@ dependencies = [ [[package]] name = "libp2p-websocket" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rw-stream-sink 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1580,11 +1614,11 @@ dependencies = [ [[package]] name = "libp2p-yamux" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "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.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1774,7 +1808,7 @@ dependencies = [ [[package]] name = "multistream-select" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2000,11 +2034,6 @@ name = "once_cell" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "opaque-debug" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "opaque-debug" version = "0.2.1" @@ -2081,11 +2110,11 @@ dependencies = [ [[package]] name = "parity-crypto" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2110,7 +2139,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2181,7 +2210,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2283,7 +2312,7 @@ dependencies = [ [[package]] name = "protobuf" -version = "2.2.5" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2358,15 +2387,16 @@ dependencies = [ [[package]] name = "rand" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2419,6 +2449,16 @@ dependencies = [ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand_jitter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_os" version = "0.1.1" @@ -2547,12 +2587,13 @@ dependencies = [ [[package]] name = "ring" -version = "0.13.5" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2820,6 +2861,27 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "snow" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "static_slice 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "spin" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "sr-api-macros" version = "0.1.0" @@ -3308,6 +3370,11 @@ name = "static_assertions" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "static_slice" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "stdweb" version = "0.4.13" @@ -3354,10 +3421,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "stream-cipher" -version = "0.1.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3395,7 +3462,7 @@ name = "subkey" version = "0.1.0" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 0.1.0", ] @@ -3638,7 +3705,7 @@ dependencies = [ "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.0.0 (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.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-client 0.1.0", "substrate-consensus-common 0.1.0", @@ -3689,8 +3756,8 @@ version = "0.1.0" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-crypto 0.3.0 (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.85 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3713,7 +3780,7 @@ dependencies = [ "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.0.0 (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.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-client 0.1.0", @@ -3734,10 +3801,10 @@ 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.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "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.4 (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.85 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3765,7 +3832,7 @@ dependencies = [ "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4073,7 +4140,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4291,7 +4358,7 @@ dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4375,7 +4442,7 @@ dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "hash-db 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4403,12 +4470,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "twofish" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4416,7 +4483,7 @@ name = "twox-hash" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4750,23 +4817,24 @@ dependencies = [ "nohash-hasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (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)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] "checksum MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eaf9f0d0b1cc33a4d2aee14fb4b2eac03462ef4db29c8ac4057327d8a71ad86f" -"checksum aes-ctr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f65958ff3692041c36fc009261ccd63f24cd8e0dc1164266f068c2387e8b4e4f" -"checksum aes-soft 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67cc03b0a090a05cb01e96998a01905d7ceedce1bc23b756c0bb7faa0682ccb1" -"checksum aesni 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6810b7fb9f2bb4f76f05ac1c170b8dde285b6308955dc3afd89710268c958d9e" +"checksum aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2e5b0458ea3beae0d1d8c0f3946564f8e10f90646cf78c06b4351052058d1ee" +"checksum aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" +"checksum aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum aio-limited 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f10b352bc3fc08ae24dc5d2d3ddcac153678533986122dc283d747b12071000" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" -"checksum asn1_der 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "766afdc5c6d7c15de1abe4c9c15e360be3aa972c363ba5b606be3c4271235886" +"checksum asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9893d63fc3b1c44231e667da6836a33f27d8b6b3bdc82f83da5dfd579d1b6528" +"checksum asn1_der_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e7f92edafad155aff997fa5b727c6429b91e996b5a5d62a2b0adbae1306b5fe" "checksum assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7deb0a829ca7bcfaf5da70b073a8d128619259a7be8216a355e23f00763059e5" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" @@ -4784,7 +4852,7 @@ dependencies = [ "checksum block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1339a1042f5d9f295737ad4d9a6ab6bf81c84a933dba110b9200cd6d1448b814" "checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" "checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" -"checksum block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "370424437b9459f3dfd68428ed9376ddfe03d8b70ede29cc533b3557df186ab4" +"checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" "checksum block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc4358306e344bf9775d0197fd00d2603e5afb0771bb353538630f022068ea3" "checksum bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0de79cfb98e7aa9988188784d8664b4b5dad6eaaa0863b91d9a4ed871d4f7a42" "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" @@ -4823,10 +4891,11 @@ dependencies = [ "checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" "checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04" "checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" -"checksum ctr 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4b669fcb8e20124db86dbd9b01e74ec0e9e420e65381311ce5249864fc7ff0c0" +"checksum ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "044f882973b245404e90c90e7e42e8ee8d7a64edfd7adf83d684fb97e8e2c1b6" "checksum ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "630391922b1b893692c6334369ff528dcc3a9d8061ccf4c803aa8f83cb13db5e" "checksum cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd43f7cfaffe0a386636a10baea2ee05cc50df3b77bea4a456c9572a939bf1f" "checksum curve25519-dalek 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3eacf6ff1b911e3170a8c400b402e10c86dc3cb166bd69034ebbc2b785fea4c2" +"checksum curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dae47cc3529cdab597dbc8b606e565707209b506e55848f3c15679214a56c956" "checksum data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f47ca1860a761136924ddd2422ba77b2ea54fe8cc75b9040804a0d9d32ad97" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5b29bf156f3f4b3c4f610a25ff69370616ae6e0657d416de22645483e72af0a" @@ -4840,7 +4909,6 @@ dependencies = [ "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" "checksum environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db746025e3ea695bfa0ae744dbacd5fcfc8db51b9760cf8bd0ab69708bb93c49" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" -"checksum etrace 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f17311e68ea07046ee809b8513f6c259518bc10173681d98c21f8c3926f56f40" "checksum exit-future 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "87559b08e99a81a92bbb867d237543e43495857749f688e0773390a20d56c61c" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" @@ -4903,23 +4971,24 @@ dependencies = [ "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.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ef2cce57e82d0decdf5464e4e179a319ee14c218c330bb017f62453f4ab74842" -"checksum libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "26977e332e88c070353864d5ed72b6e1175fc1c63af5709b5174877836a229b6" -"checksum libp2p-core-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8a88f076f3f60f3f407ce4fc0f620e3592125461bec5aa4895316e1f0414b3ea" -"checksum libp2p-dns 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f7ad92f9711efece48bb7ce30e3f1e662cd3524dc5d9f96b8f68b6e4e7cde96" -"checksum libp2p-floodsub 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4feda0ff3afcf84dfee9ea088835293829d199a34491d7f0990a4ccfd627816c" -"checksum libp2p-identify 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "548f9180101bd5846f4f60e060a00032ba3671a77fc735c48a85b7d1016d28ef" -"checksum libp2p-kad 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91c28bf179a22fd1bfa3bad28ed86b8657ed2d193b76caa6f632ea83356d3a40" -"checksum libp2p-mdns 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1bbcb82063545605abf697967d919d418b1725f7d3688973fa26c98f81e8cda8" -"checksum libp2p-mplex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9406ea58ce4fef47820f7d2d6aa62b7e42b4972c30cc87de577d4da40852d4b1" -"checksum libp2p-ping 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c1ca7b60c2edb0cae7f9db56fbe6c21ca6960e96ec92cd1ed265ac06db24a1fe" -"checksum libp2p-plaintext 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84bdbdd4700d5edea10214e4733ab5ac5be87862bac8a9b259c987bc9c15004" -"checksum libp2p-ratelimit 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d3001ea6afed5ccd1e5934715aa388b60b23e7587117db36b89d697e8ea43ff3" -"checksum libp2p-secio 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc2bee2dce0d0d054d81447b06f7e923f1a98e6b240e42674e0fdf2e4a4924f" -"checksum libp2p-tcp 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fcb2bcb9402f5fe42441dd4558306ff83a28624f67c6066bdbaa98928c180e3" -"checksum libp2p-uds 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3e88ac8f419f8d9487aaee9ef8785f592b37d78067c6764fe0adc1874a72c6c" -"checksum libp2p-websocket 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80b60b65b8d7053220a0c78a09eda0a162db410067639d2b24432a9f1dc06230" -"checksum libp2p-yamux 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71b4fd69a1c038152d017366d759177e2580fb4fbb56ce65429a642e011a07b1" +"checksum libp2p 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3462538e41bc5ebd047ce06948aaeaffb19f5106d3972a1a9f4a8bddf632503" +"checksum libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a318966714e3932b6760fc0a4222bb18759b1145f23288839f907d6de39408a3" +"checksum libp2p-core-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d4a19eddef3a04798b4f7aa210c53f300390a1c1d409eee5261628abd1d5ef6" +"checksum libp2p-dns 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a822c32da15ab0c4451792a4b000c37fbf8e3bc5ac471632f0b1f13e8e555524" +"checksum libp2p-floodsub 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4380fbc42ec03251c9e9a4656744e8e88bbe59cbf4e084fa66370ed0b868d085" +"checksum libp2p-identify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "583eb9c0ee46457e1dfe3495a0a306467ee7ab287d17e19fda392106acc8f166" +"checksum libp2p-kad 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23dcdef64ac7f12a10de5461ab053fe5392f15fb7a7127d9e00f8a4b49732f92" +"checksum libp2p-mdns 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4388af57ce8144eb0f6719926139df4f728042931eee5a32daf783a2fc9e05" +"checksum libp2p-mplex 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58e4dcf1b8ee62d872ff38134969b0a2d63d014c200748eead158c58512a0c1b" +"checksum libp2p-noise 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9beca4939eb183708b8f172170044d977f1264394998e183efbf4972e09c163f" +"checksum libp2p-ping 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60d3acc575adbf6723b0965eca131e2525bed2c85ec88ddc4bff0462dbc0c2c3" +"checksum libp2p-plaintext 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b7cae333f78b782907d9940cb8dca37ddfa353fcaa812172654969fa65ef280c" +"checksum libp2p-ratelimit 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e298aa8036653ab9d4c37376066cb2fc69f63115522a9a3d402fcdc1654612ea" +"checksum libp2p-secio 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3495935a389a6f4b26e71f9d6eac3fc33a9481f5f5d79ad886d5bc7efe0195c3" +"checksum libp2p-tcp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ae301dcdd52087d40a106971575144c4f6220b37e0d1d98474085445327e2708" +"checksum libp2p-uds 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5524df7a63d97a8bbe2064d6bc85a84594ad71a8fad4b82ae958fbe37770ce" +"checksum libp2p-websocket 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e80602e23cf58b92d47142a32560c19417f8e9113017eb105f5e580f3bbeb8bc" +"checksum libp2p-yamux 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de9a2ed873051c7a85ec7dece746d425564c366b87752e83056c33d8ae758dcf" "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" @@ -4941,7 +5010,7 @@ dependencies = [ "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.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "886fe7ba983a194afdd9074323171c8e313b2c145561da69464d5443f1a3d121" +"checksum multistream-select 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ed84364f0e921a32204896952ee80c7befc14a7a39f2c56cd955d71e8dae6" "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" @@ -4954,7 +5023,6 @@ dependencies = [ "checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" "checksum once_cell 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "53075ac5dbd2798cfbcf9f710f2737de031d8076c192d8fe66fb23f639ccbdf4" -"checksum opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d620c9c26834b34f039489ac0dfdb12c7ac15ccaf818350a64c9b5334a452ad7" "checksum opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "51ecbcb821e1bd256d456fe858aaa7f380b63863eab2eb86eee1bd9f33dd6682" "checksum openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" @@ -4964,7 +5032,7 @@ dependencies = [ "checksum parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" "checksum parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88f69984317b736dceac3baa86600fc089856f69b44b07231f39b5648b02bcd4" "checksum parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a58ba33211595f92cc2163ac583961d3dc767e656934146636b05256cc9acd7f" -"checksum parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8adf489acb31f1922db0ce43803b6f48a425241a8473611be3cc625a8e4a4c47" +"checksum parity-crypto 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b9db194dfbcfe3b398d63d765437a5c7232d59906e203055f0e993f6458ff1" "checksum parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9a8e5d637787fe097ec1bfca2aa3eb687396518003df991c6c7216d86682d5ff" "checksum parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e8eab0287ccde7821e337a124dc5a4f1d6e4c25d10cc91e3f9361615dd95076" "checksum parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)" = "511379a8194230c2395d2f5fa627a5a7e108a9f976656ce723ae68fca4097bfc" @@ -4986,7 +5054,7 @@ dependencies = [ "checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a" "checksum proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "77997c53ae6edd6d187fec07ec41b207063b5ee6f33680e9fa86d405cdd313d4" "checksum proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "38fddd23d98b2144d197c0eca5705632d4fe2667d14a6be5df8934f8d74f1978" -"checksum protobuf 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f1dae61c65148faf4bcc242624a08687e5076f68fa958cb6b7fc66049954a77d" +"checksum protobuf 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d82d117bc7565ce6be0150159251c9b1eeec7b129f5a2aa86e10acb5970de1cb" "checksum pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "efb0dcbddbb600f47a7098d33762a00552c671992171637f5bb310b37fe1f0e4" "checksum quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb6ccf8db7bbcb9c2eae558db5ab4f3da1c2a87e4e597ed394726bc8ea6ca1d" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" @@ -4995,13 +5063,14 @@ dependencies = [ "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dee497e66d8d76bf08ce20c8d36e16f93749ab0bf89975b4f8ae5cee660c2da2" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" -"checksum rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3906503e80ac6cbcacb2c2973fa8e473f24d7e2747c8c92bb230c2441cad96b5" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_jitter 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "080723c6145e37503a2224f801f252e14ac5531cb450f4502698542d188cb3c0" "checksum rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46fbd5550acf75b0c2730f5dd1873751daf9beb8f11b44027778fae50d7feca" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" @@ -5016,7 +5085,7 @@ dependencies = [ "checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum rhododendron 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9381ed76c1ec4e8994f1f7d2c6d7e33eed3ff7176e16fece09c2e993fc4a5a" -"checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a" +"checksum ring 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)" = "148fc853f6d85f53f5f315d46701eaacc565cdfb3cb1959730c96e81e7e49999" "checksum rocksdb 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1651697fefd273bfb4fd69466cc2a9d20de557a0213b97233b22b5e95924b5e" "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" @@ -5050,13 +5119,16 @@ dependencies = [ "checksum slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" "checksum slog-scope 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "60c04b4726fa04595ccf2c2dad7bcd15474242c4c5e109a8a376e8a2c9b1539a" "checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" +"checksum snow 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2ce0dd923ee41918b1e5a63f19d6443fa3d951868a87b691bd30674e91ad5aa2" +"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" +"checksum static_slice 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "92a7e0c5e3dfb52e8fbe0e63a1b947bbb17b4036408b151353c4491374931362" "checksum stdweb 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "461e7f2e33670b1c33f1ea22bb2f86de6136fabd0c4d27d167ed425c231143ca" "checksum stdweb-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e21ebd9179de08f2300a65454268a17ea3de204627458588c84319c4def3930" "checksum stdweb-internal-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "432465093692af7379dcd196ce4be398c906958d91b412fff9102a66238d6f26" "checksum stdweb-internal-runtime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a2a2f4a2eb556337b2d1a302630bbddf989ae383c70393e89b48152b9896cbda" -"checksum stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "30dc6118470d69ce0fdcf7e6f95e95853f7f4f72f80d835d4519577c323814ab" +"checksum stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8861bc80f649f5b4c9bd38b696ae9af74499d479dbfb327f0607de6b326a36bc" "checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" @@ -5099,7 +5171,7 @@ dependencies = [ "checksum trie-root 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6294c313431d8bd2dda88db3a57550c4911dd6f7f0e8be6001e23c1e6cbdcf1b" "checksum trie-standardmap 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "30da337fb1e61993d3f6a6fed2957d13f7a604097e34d1ea9715c2f0b2df616e" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" -"checksum twofish 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1eef327f05b0d0ec1b9d7d119d8f4d9f602ceee37e0540aff8071e8e66c2e22e" +"checksum twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d261e83e727c8e2dbb75dacac67c36e35db36a958ee504f2164fc052434e1" "checksum twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "555cd4909480122bbbf21e34faac4cb08a171f324775670447ed116726c474af" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" diff --git a/core/keystore/Cargo.toml b/core/keystore/Cargo.toml index d5dd0cbca9b1d..9a028d21d975c 100644 --- a/core/keystore/Cargo.toml +++ b/core/keystore/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] substrate-primitives = { path = "../primitives" } -crypto = { package = "parity-crypto", version = "0.2", default-features = false } +crypto = { package = "parity-crypto", version = "0.3", default-features = false } error-chain = "0.12" hex = "0.3" rand = "0.6" diff --git a/core/keystore/src/lib.rs b/core/keystore/src/lib.rs index 63da247970d9b..ed311d1653357 100644 --- a/core/keystore/src/lib.rs +++ b/core/keystore/src/lib.rs @@ -24,6 +24,7 @@ use std::collections::HashMap; use std::path::PathBuf; use std::fs::{self, File}; use std::io::{self, Write}; +use std::num::NonZeroU32; use serde_derive::{Serialize, Deserialize}; use error_chain::{error_chain, error_chain_processing, impl_error_chain_processed, @@ -60,11 +61,11 @@ struct EncryptedKey { salt: [u8; 32], ciphertext: Vec, // FIXME: switch to fixed-size when serde supports iv: [u8; 16], - iterations: u32, + iterations: NonZeroU32, } impl EncryptedKey { - fn encrypt(plain: &[u8; PKCS_LEN], password: &str, iterations: u32) -> Self { + fn encrypt(plain: &[u8; PKCS_LEN], password: &str, iterations: NonZeroU32) -> Self { use rand::{Rng, rngs::OsRng}; let mut rng = OsRng::new().expect("OS Randomness available on all supported platforms; qed"); @@ -149,7 +150,11 @@ impl Store { /// Generate a new key, placing it into the store. pub fn generate(&self, password: &str) -> Result { let (pair, pkcs_bytes) = Pair::generate_with_pkcs8(); - let key_file = EncryptedKey::encrypt(&pkcs_bytes, password, KEY_ITERATIONS as u32); + let key_file = EncryptedKey::encrypt( + &pkcs_bytes, + password, + NonZeroU32::new(KEY_ITERATIONS as u32).expect("KEY_ITERATIONS is not zero; QED") + ); let mut file = File::create(self.key_file_path(&pair.public()))?; ::serde_json::to_writer(&file, &key_file)?; diff --git a/core/network-libp2p/Cargo.toml b/core/network-libp2p/Cargo.toml index 65235da5b998d..e8f0f97d25662 100644 --- a/core/network-libp2p/Cargo.toml +++ b/core/network-libp2p/Cargo.toml @@ -12,7 +12,7 @@ bytes = "0.4" error-chain = { version = "0.12", default-features = false } fnv = "1.0" futures = "0.1" -libp2p = { version = "0.2", default-features = false, features = ["secio-rsa", "secio-secp256k1", "libp2p-websocket"] } +libp2p = { version = "0.3.0", default-features = false, features = ["secio-secp256k1", "libp2p-websocket"] } parking_lot = "0.7.1" lazy_static = "1.2" log = "0.4" diff --git a/core/network-libp2p/src/behaviour.rs b/core/network-libp2p/src/behaviour.rs index d29be123077bb..5011a8a3c14ca 100644 --- a/core/network-libp2p/src/behaviour.rs +++ b/core/network-libp2p/src/behaviour.rs @@ -19,11 +19,11 @@ use crate::{NetworkConfiguration, ProtocolId}; use bytes::Bytes; use futures::prelude::*; use libp2p::NetworkBehaviour; -use libp2p::core::{PeerId, ProtocolsHandler}; +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, KademliaTopology}; +use libp2p::kad::{Kademlia, KademliaOut, KadConnectionType}; use libp2p::ping::{Ping, PingEvent}; use log::{debug, trace, warn}; use std::{cmp, io, time::Duration, time::Instant}; @@ -51,17 +51,20 @@ pub struct Behaviour { impl Behaviour { /// Builds a new `Behaviour`. - // TODO: redundancy between config and local_peer_id (https://github.com/libp2p/rust-libp2p/issues/745) - pub fn new(config: &NetworkConfiguration, local_peer_id: PeerId, protocols: RegisteredProtocols) -> Self { + // 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: RegisteredProtocols) -> 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) + Identify::new(proto_version, user_agent, local_public_key.clone()) }; + let local_peer_id = local_public_key.into_peer_id(); + let custom_protocols = CustomProtos::new(config, &local_peer_id, protocols); + Behaviour { ping: Ping::new(), - custom_protocols: CustomProtos::new(config, protocols), + custom_protocols, discovery: DiscoveryBehaviour::new(local_peer_id), identify, events: Vec::new(), @@ -79,9 +82,26 @@ impl Behaviour { self.custom_protocols.send_packet(target, protocol_id, 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(); + } + /// Try to add a reserved peer. - pub fn add_reserved_peer(&mut self, peer_id: PeerId) { - self.custom_protocols.add_reserved_peer(peer_id) + 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. @@ -218,6 +238,10 @@ impl NetworkBehaviourEventProcess for Behaviour {} @@ -227,10 +251,13 @@ impl NetworkBehaviourEventProcess for Behaviour NetworkBehaviourEventProcess for Behaviour { fn inject_event(&mut self, out: KademliaOut) { - // We only ever use Kademlia for discovering nodes, and nodes discovered by Kademlia are - // automatically added to the topology. Therefore we don't need to perform any further - // action. 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::FindNodeResult { key, closer_peers } => { trace!(target: "sub-libp2p", "Kademlia query for {:?} yielded {:?} results", key, closer_peers.len()); @@ -284,24 +311,27 @@ impl DiscoveryBehaviour { } } -impl NetworkBehaviour for DiscoveryBehaviour +impl NetworkBehaviour for DiscoveryBehaviour where TSubstream: AsyncRead + AsyncWrite, - TTopology: KademliaTopology, { - type ProtocolsHandler = as NetworkBehaviour>::ProtocolsHandler; - type OutEvent = as NetworkBehaviour>::OutEvent; + type ProtocolsHandler = as NetworkBehaviour>::ProtocolsHandler; + type OutEvent = as NetworkBehaviour>::OutEvent; fn new_handler(&mut self) -> Self::ProtocolsHandler { - NetworkBehaviour::::new_handler(&mut self.kademlia) + NetworkBehaviour::new_handler(&mut self.kademlia) + } + + fn addresses_of_peer(&mut self, peer_id: &PeerId) -> Vec { + self.kademlia.addresses_of_peer(peer_id) } fn inject_connected(&mut self, peer_id: PeerId, endpoint: ConnectedPoint) { - NetworkBehaviour::::inject_connected(&mut self.kademlia, peer_id, endpoint) + NetworkBehaviour::inject_connected(&mut self.kademlia, peer_id, endpoint) } fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) { - NetworkBehaviour::::inject_disconnected(&mut self.kademlia, peer_id, endpoint) + NetworkBehaviour::inject_disconnected(&mut self.kademlia, peer_id, endpoint) } fn inject_node_event( @@ -309,12 +339,12 @@ where peer_id: PeerId, event: ::OutEvent, ) { - NetworkBehaviour::::inject_node_event(&mut self.kademlia, peer_id, event) + NetworkBehaviour::inject_node_event(&mut self.kademlia, peer_id, event) } fn poll( &mut self, - params: &mut PollParameters, + params: &mut PollParameters, ) -> Async< NetworkBehaviourAction< ::InEvent, diff --git a/core/network-libp2p/src/custom_proto/behaviour.rs b/core/network-libp2p/src/custom_proto/behaviour.rs index 6fe68e308c2e3..ba38442eb2ed5 100644 --- a/core/network-libp2p/src/custom_proto/behaviour.rs +++ b/core/network-libp2p/src/custom_proto/behaviour.rs @@ -15,19 +15,23 @@ // along with Substrate. If not, see . use crate::custom_proto::handler::{CustomProtosHandler, CustomProtosHandlerOut, CustomProtosHandlerIn}; +use crate::custom_proto::topology::NetTopology; use crate::custom_proto::upgrade::RegisteredProtocols; -use crate::{NetworkConfiguration, NonReservedPeerMode, ProtocolId, topology::NetTopology}; +use crate::{NetworkConfiguration, NonReservedPeerMode, ProtocolId}; +use crate::parse_str_addr; use bytes::Bytes; use fnv::{FnvHashMap, FnvHashSet}; use futures::prelude::*; use libp2p::core::swarm::{ConnectedPoint, NetworkBehaviour, NetworkBehaviourAction, PollParameters}; -use libp2p::core::{protocols_handler::ProtocolsHandler, PeerId}; +use libp2p::core::{protocols_handler::ProtocolsHandler, Multiaddr, PeerId}; use log::{debug, trace, warn}; use smallvec::SmallVec; -use std::{io, marker::PhantomData, time::Duration, time::Instant}; +use std::{error, io, marker::PhantomData, path::Path, time::Duration, time::Instant}; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_timer::Delay; +// File where the network topology is stored. +const NODES_FILE: &str = "nodes.json"; // Duration during which a peer is disabled. const PEER_DISABLE_DURATION: Duration = Duration::from_secs(5 * 60); @@ -36,6 +40,9 @@ pub struct CustomProtos { /// List of protocols to open with peers. Never modified. registered_protocols: RegisteredProtocols, + /// Topology of the network. + topology: NetTopology, + /// List of custom protocols that we have open with remotes. open_protocols: Vec<(PeerId, ProtocolId)>, @@ -122,7 +129,27 @@ pub enum CustomProtosOut { impl CustomProtos { /// Creates a `CustomProtos`. - pub fn new(config: &NetworkConfiguration, registered_protocols: RegisteredProtocols) -> Self { + pub fn new(config: &NetworkConfiguration, local_peer_id: &PeerId, registered_protocols: RegisteredProtocols) -> Self { + // Initialize the topology of the network. + let mut topology = if let Some(ref path) = config.net_config_path { + let path = Path::new(path).join(NODES_FILE); + debug!(target: "sub-libp2p", "Initializing peer store for JSON file {:?}", path); + NetTopology::from_file(local_peer_id.clone(), path) + } else { + debug!(target: "sub-libp2p", "No peers file configured ; peers won't be saved"); + NetTopology::memory(local_peer_id.clone()) + }; + + // Register the external addresses provided by the user as our own. + topology.add_external_addrs(config.public_addresses.clone().into_iter()); + + // Add the bootstrap nodes to the topology. + for bootnode in config.boot_nodes.iter() { + if let Ok((peer_id, addr)) = parse_str_addr(bootnode) { + topology.add_bootstrap_addr(&peer_id, addr.clone()); + } + } + let max_incoming_connections = config.in_peers as usize; let max_outgoing_connections = config.out_peers as usize; @@ -136,6 +163,7 @@ impl CustomProtos { CustomProtos { registered_protocols, + topology, max_incoming_connections, max_outgoing_connections, reserved_only: config.non_reserved_mode == NonReservedPeerMode::Deny, @@ -150,7 +178,8 @@ impl CustomProtos { } /// Adds a reserved peer. - pub fn add_reserved_peer(&mut self, peer_id: PeerId) { + pub fn add_reserved_peer(&mut self, peer_id: PeerId, addr: Multiaddr) { + self.topology.add_bootstrap_addr(&peer_id, addr); self.reserved_peers.insert(peer_id); // Trigger a `connect_to_nodes` round. @@ -240,11 +269,40 @@ impl CustomProtos { }); } + /// Indicates to the topology that we have discovered new addresses for a given node. + pub fn add_discovered_addrs( + &mut self, + peer_id: &PeerId, + addrs: I, + ) where I: Iterator { + if self.topology.add_discovered_addrs(peer_id, addrs) { + // Trigger a `connect_to_nodes` round. + self.next_connect_to_nodes = Delay::new(Instant::now()); + } + } + + /// Returns the number of peers in the topology. + pub fn num_topology_peers(&self) -> usize { + self.topology.num_peers() + } + + /// Flushes the topology to the disk. + pub fn flush_topology(&mut self) -> Result<(), io::Error> { + self.topology.flush_to_disk() + } + + /// Perform a cleanup pass, removing all obsolete addresses and peers. + /// + /// This should be done from time to time. + pub fn cleanup(&mut self) { + self.topology.cleanup(); + } + /// Updates the attempted connections to nodes. /// /// Also updates `next_connect_to_nodes` with the earliest known moment when we need to /// update connections again. - fn connect_to_nodes(&mut self, params: &mut PollParameters) { + fn connect_to_nodes(&mut self, params: &mut PollParameters) { // Make sure we are connected or connecting to all the reserved nodes. for reserved in self.reserved_peers.iter() { // TODO: don't generate an event if we're already in a pending connection (https://github.com/libp2p/rust-libp2p/issues/697) @@ -272,7 +330,7 @@ impl CustomProtos { num_to_open); let local_peer_id = params.local_peer_id().clone(); - let (to_try, will_change) = params.topology().addrs_to_attempt(); + let (to_try, will_change) = self.topology.addrs_to_attempt(); for (peer_id, _) in to_try { if num_to_open == 0 { break @@ -297,7 +355,7 @@ impl CustomProtos { } } -impl NetworkBehaviour for CustomProtos +impl NetworkBehaviour for CustomProtos where TSubstream: AsyncRead + AsyncWrite, { @@ -308,6 +366,10 @@ where CustomProtosHandler::new(self.registered_protocols.clone()) } + fn addresses_of_peer(&mut self, peer_id: &PeerId) -> Vec { + self.topology.addresses_of_peer(peer_id) + } + fn inject_connected(&mut self, peer_id: PeerId, endpoint: ConnectedPoint) { // When a peer connects, its handler is initially in the disabled state. We make sure that // the peer is allowed, and if so we put it in the enabled state. @@ -374,10 +436,13 @@ where }); } + self.topology.set_connected(&peer_id, &endpoint); self.enabled_peers.insert(peer_id, endpoint); } - fn inject_disconnected(&mut self, peer_id: &PeerId, _: ConnectedPoint) { + fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) { + self.topology.set_disconnected(peer_id, &endpoint); + while let Some(pos) = self.open_protocols.iter().position(|(p, _)| p == peer_id) { let (_, protocol_id) = self.open_protocols.remove(pos); @@ -396,6 +461,13 @@ where self.enabled_peers.remove(peer_id); } + fn inject_dial_failure(&mut self, peer_id: Option<&PeerId>, addr: &Multiaddr, error: &dyn error::Error) { + debug!(target: "sub-libp2p", "Failed to reach peer {:?} through {} => {:?}", peer_id, addr, error); + self.topology.set_unreachable(addr); + // Trigger a `connect_to_nodes` round. + self.next_connect_to_nodes = Delay::new(Instant::now()); + } + fn inject_node_event( &mut self, source: PeerId, @@ -461,7 +533,7 @@ where fn poll( &mut self, - params: &mut PollParameters, + params: &mut PollParameters, ) -> Async< NetworkBehaviourAction< ::InEvent, diff --git a/core/network-libp2p/src/custom_proto/handler.rs b/core/network-libp2p/src/custom_proto/handler.rs index c90276095d7dd..749259dcb3e6d 100644 --- a/core/network-libp2p/src/custom_proto/handler.rs +++ b/core/network-libp2p/src/custom_proto/handler.rs @@ -20,12 +20,13 @@ use bytes::Bytes; use futures::prelude::*; use libp2p::core::{ Endpoint, ProtocolsHandler, ProtocolsHandlerEvent, + protocols_handler::KeepAlive, protocols_handler::ProtocolsHandlerUpgrErr, upgrade::{InboundUpgrade, OutboundUpgrade} }; use log::{trace, warn}; use smallvec::SmallVec; -use std::{fmt, io}; +use std::{fmt, io, time::Duration, time::Instant}; use tokio_io::{AsyncRead, AsyncWrite}; use void::Void; @@ -42,6 +43,9 @@ pub struct CustomProtosHandler { /// See the documentation of `State`. state: State, + /// Value to be returned by `connection_keep_alive()`. + keep_alive: KeepAlive, + /// The active substreams. There should always ever be only one substream per protocol. substreams: SmallVec<[RegisteredProtocolSubstream; 6]>, @@ -130,6 +134,8 @@ where pub fn new(protocols: RegisteredProtocols) -> Self { CustomProtosHandler { protocols, + // We keep the connection alive for at least 5 seconds, waiting for what happens. + keep_alive: KeepAlive::Until(Instant::now() + Duration::from_secs(5)), state: State::Disabled, substreams: SmallVec::new(), events_queue: SmallVec::new(), @@ -203,6 +209,7 @@ where State::Disabled | State::ShuttingDown => (), } + self.keep_alive = KeepAlive::Now; for substream in self.substreams.iter_mut() { substream.shutdown(); } @@ -213,6 +220,8 @@ where State::Normal | State::ShuttingDown => (), } + self.keep_alive = KeepAlive::Forever; + // Try open one substream for each registered protocol. if let CustomProtosHandlerIn::EnableActive = message { for protocol in self.protocols.0.iter() { @@ -253,14 +262,16 @@ where #[inline] fn inject_dial_upgrade_error(&mut self, _: Self::OutboundOpenInfo, err: ProtocolsHandlerUpgrErr) { warn!(target: "sub-libp2p", "Error while opening custom protocol: {:?}", err); - } - #[inline] - fn connection_keep_alive(&self) -> bool { // Right now if the remote doesn't support one of the custom protocols, we shut down the // entire connection. This is a hack-ish solution to the problem where we connect to nodes // that support libp2p but not the testnet that we want. - self.substreams.len() == self.protocols.len() + self.shutdown(); + } + + #[inline] + fn connection_keep_alive(&self) -> KeepAlive { + self.keep_alive } fn shutdown(&mut self) { diff --git a/core/network-libp2p/src/custom_proto/mod.rs b/core/network-libp2p/src/custom_proto/mod.rs index f8b7e8edc5b2a..d140571132bf7 100644 --- a/core/network-libp2p/src/custom_proto/mod.rs +++ b/core/network-libp2p/src/custom_proto/mod.rs @@ -19,4 +19,5 @@ pub use self::upgrade::{RegisteredProtocol, RegisteredProtocols}; mod behaviour; mod handler; +mod topology; mod upgrade; diff --git a/core/network-libp2p/src/topology.rs b/core/network-libp2p/src/custom_proto/topology.rs similarity index 86% rename from core/network-libp2p/src/topology.rs rename to core/network-libp2p/src/custom_proto/topology.rs index 6689caf4b0318..f033f5a632cc4 100644 --- a/core/network-libp2p/src/topology.rs +++ b/core/network-libp2p/src/custom_proto/topology.rs @@ -15,12 +15,10 @@ // along with Substrate. If not, see .? use fnv::FnvHashMap; -use libp2p::{Multiaddr, PeerId, identify::IdentifyTopology, multihash::Multihash}; -use libp2p::core::{PublicKey, swarm::ConnectedPoint, topology::DisconnectReason, topology::Topology}; -use libp2p::kad::{KBucketsPeerId, KadConnectionType, KademliaTopology}; +use libp2p::{core::swarm::ConnectedPoint, Multiaddr, PeerId}; use log::{debug, info, trace, warn}; use serde_derive::{Serialize, Deserialize}; -use std::{cmp, fs, iter, vec}; +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}; @@ -58,8 +56,6 @@ 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); -// TODO: should be merged with the Kademlia k-buckets - /// Stores information about the topology of the network. #[derive(Debug)] pub struct NetTopology { @@ -67,9 +63,7 @@ pub struct NetTopology { store: FnvHashMap, /// Optional path to the file that caches the serialized version of `store`. cache_path: Option, - /// Public key of the local node. - local_public_key: PublicKey, - /// PeerId of the local node. Derived from `local_public_key`. + /// PeerId of the local node. local_peer_id: PeerId, /// Known addresses for the local node to report to the network. external_addresses: Vec, @@ -80,13 +74,11 @@ impl NetTopology { /// /// `flush_to_disk()` will be a no-op. #[inline] - pub fn memory(local_public_key: PublicKey) -> NetTopology { - let local_peer_id = local_public_key.clone().into_peer_id(); + pub fn memory(local_peer_id: PeerId) -> NetTopology { NetTopology { store: Default::default(), cache_path: None, local_peer_id, - local_public_key, external_addresses: Vec::new(), } } @@ -97,16 +89,14 @@ impl NetTopology { /// or contains garbage data, the execution still continues. /// /// Calling `flush_to_disk()` in the future writes to the given path. - pub fn from_file>(local_public_key: PublicKey, path: P) -> NetTopology { + pub fn from_file>(local_peer_id: PeerId, path: P) -> NetTopology { let path = path.as_ref(); - let local_peer_id = local_public_key.clone().into_peer_id(); 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, - local_public_key, external_addresses: Vec::new(), } } @@ -235,10 +225,11 @@ impl NetTopology { } } - /// Inner implementaiton of the `add_*_discovered_addrs` methods. + /// 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. - fn add_discovered_addrs( + pub fn add_discovered_addrs( &mut self, peer_id: &PeerId, addrs: I, @@ -308,54 +299,10 @@ impl NetTopology { anything_changed } -} - -impl KademliaTopology for NetTopology { - type ClosestPeersIter = vec::IntoIter; - type GetProvidersIter = iter::Empty; - - fn add_kad_discovered_address(&mut self, peer: PeerId, addr: Multiaddr, ty: KadConnectionType) { - self.add_discovered_addrs(&peer, iter::once((addr, ty == KadConnectionType::Connected))); - } - - fn closest_peers(&mut self, target: &Multihash, _max: usize) -> Self::ClosestPeersIter { - // TODO: very inefficient - let mut peers = self.store.keys().cloned().collect::>(); - peers.push(self.local_peer_id.clone()); - peers.sort_by(|a, b| { - b.as_ref().distance_with(target).cmp(&a.as_ref().distance_with(target)) - }); - peers.into_iter() - } - - fn add_provider(&mut self, _: Multihash, _: PeerId) { - // We don't implement ADD_PROVIDER/GET_PROVIDERS - } - - fn get_providers(&mut self, _: &Multihash) -> Self::GetProvidersIter { - // We don't implement ADD_PROVIDER/GET_PROVIDERS - iter::empty() - } -} -impl IdentifyTopology for NetTopology { + /// Returns the addresses stored for a specific peer. #[inline] - fn add_identify_discovered_addrs(&mut self, peer: &PeerId, addrs: TIter) - where - TIter: Iterator - { - // These are addresses that peers indicate for themselves. - // The typical use case is: - // - A peer connects to one of our listening points. - // - We send an identify request to it, and it answers with a list of addresses. - // - If later it disconnects, we can try to dial it back through one of these addresses. - self.add_discovered_addrs(peer, addrs.map(move |a| (a, true))); - } -} - -impl Topology for NetTopology { - #[inline] - fn addresses_of_peer(&mut self, peer: &PeerId) -> Vec { + pub fn addresses_of_peer(&mut self, peer: &PeerId) -> Vec { if peer == &self.local_peer_id { return self.external_addresses.clone() } @@ -382,20 +329,8 @@ impl Topology for NetTopology { list.into_iter().map(|(_, addr)| addr.clone()).collect::>() } - fn add_local_external_addrs(&mut self, addrs: TIter) - where TIter: Iterator { - self.add_external_addrs(addrs) - } - - fn local_peer_id(&self) -> &PeerId { - &self.local_peer_id - } - - fn local_public_key(&self) -> &PublicKey { - &self.local_public_key - } - - fn set_connected(&mut self, peer: &PeerId, endpoint: &ConnectedPoint) { + /// Marks the given peer as connected through the given endpoint. + pub fn set_connected(&mut self, peer: &PeerId, endpoint: &ConnectedPoint) { let addr = match endpoint { ConnectedPoint::Dialer { address } => address, ConnectedPoint::Listener { .. } => return @@ -438,17 +373,16 @@ impl Topology for NetTopology { } } - fn set_disconnected(&mut self, _: &PeerId, endpoint: &ConnectedPoint, reason: DisconnectReason) { + /// 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 }; - let score_diff = match reason { - DisconnectReason::Replaced => -3, - DisconnectReason::Graceful => -1, - DisconnectReason::Error => -5, - }; + // 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() { @@ -466,7 +400,8 @@ impl Topology for NetTopology { } } - fn set_unreachable(&mut self, addr: &Multiaddr) { + /// 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 { diff --git a/core/network-libp2p/src/lib.rs b/core/network-libp2p/src/lib.rs index 5204e38949b1e..448d39e9c6b95 100644 --- a/core/network-libp2p/src/lib.rs +++ b/core/network-libp2p/src/lib.rs @@ -21,7 +21,6 @@ mod custom_proto; mod error; mod secret; mod service_task; -mod topology; mod traits; mod transport; diff --git a/core/network-libp2p/src/service_task.rs b/core/network-libp2p/src/service_task.rs index 83e583180ad6f..5d3ec6545dd41 100644 --- a/core/network-libp2p/src/service_task.rs +++ b/core/network-libp2p/src/service_task.rs @@ -19,7 +19,6 @@ use crate::{ transport }; use crate::custom_proto::{RegisteredProtocol, RegisteredProtocols}; -use crate::topology::NetTopology; use crate::{Error, NetworkConfiguration, NodeIndex, ProtocolId, parse_str_addr}; use bytes::Bytes; use fnv::FnvHashMap; @@ -37,9 +36,6 @@ use std::sync::Arc; use std::time::Duration; use tokio_timer::Interval; -// File where the network topology is stored. -const NODES_FILE: &str = "nodes.json"; - /// Starts the substrate libp2p service. /// /// Returns a stream that must be polled regularly in order for the networking to function. @@ -58,25 +54,12 @@ where TProtos: IntoIterator { let local_public_key = local_private_key.to_public_key(); let local_peer_id = local_public_key.clone().into_peer_id(); - // Initialize the topology of the network. - let mut topology = if let Some(ref path) = config.net_config_path { - let path = Path::new(path).join(NODES_FILE); - debug!(target: "sub-libp2p", "Initializing peer store for JSON file {:?}", path); - NetTopology::from_file(local_public_key, path) - } else { - debug!(target: "sub-libp2p", "No peers file configured ; peers won't be saved"); - NetTopology::memory(local_public_key) - }; - - // Register the external addresses provided by the user as our own. - topology.add_external_addrs(config.public_addresses.clone().into_iter()); - // Build the swarm. let (mut swarm, bandwidth) = { let registered_custom = RegisteredProtocols(registered_custom.into_iter().collect()); - let behaviour = Behaviour::new(&config, local_peer_id.clone(), registered_custom); + let behaviour = Behaviour::new(&config, local_public_key.clone(), registered_custom); let (transport, bandwidth) = transport::build_transport(local_private_key); - (Swarm::new(transport, behaviour, topology), bandwidth) + (Swarm::new(transport, behaviour, local_peer_id.clone()), bandwidth) }; // Listen on multiaddresses. @@ -90,11 +73,10 @@ where TProtos: IntoIterator { } } - // Add the bootstrap nodes to the topology and connect to them. + // Connect to the bootnodes. for bootnode in config.boot_nodes.iter() { match parse_str_addr(bootnode) { - Ok((peer_id, addr)) => { - Swarm::topology_mut(&mut swarm).add_bootstrap_addr(&peer_id, addr.clone()); + Ok((peer_id, _)) => { Swarm::dial(&mut swarm, peer_id); }, Err(_) => { @@ -121,8 +103,7 @@ where TProtos: IntoIterator { // Initialize the reserved peers. for reserved in config.reserved_nodes.iter() { if let Ok((peer_id, addr)) = parse_str_addr(reserved) { - Swarm::topology_mut(&mut swarm).add_bootstrap_addr(&peer_id, addr); - swarm.add_reserved_peer(peer_id.clone()); + 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); @@ -130,7 +111,7 @@ where TProtos: IntoIterator { } debug!(target: "sub-libp2p", "Topology started with {} entries", - Swarm::topology_mut(&mut swarm).num_peers()); + swarm.num_topology_peers()); Ok(Service { swarm, @@ -198,7 +179,7 @@ pub enum ServiceEvent { /// Network service. Must be polled regularly in order for the networking to work. pub struct Service { /// Stream of events of the swarm. - swarm: Swarm, Behaviour>, NetTopology>, + swarm: Swarm, Behaviour>>, /// Bandwidth logging system. Can be queried to know the average bandwidth consumed. bandwidth: Arc, @@ -264,8 +245,7 @@ impl Service { /// Try to add a reserved peer. pub fn add_reserved_peer(&mut self, peer_id: PeerId, addr: Multiaddr) { - Swarm::topology_mut(&mut self.swarm).add_bootstrap_addr(&peer_id, addr); - self.swarm.add_reserved_peer(peer_id); + self.swarm.add_reserved_peer(peer_id, addr); } /// Try to remove a reserved peer. @@ -435,13 +415,13 @@ impl Service { Ok(Async::NotReady) => return Ok(Async::NotReady), Ok(Async::Ready(Some(_))) => { debug!(target: "sub-libp2p", "Cleaning and flushing topology"); - Swarm::topology_mut(&mut self.swarm).cleanup(); - if let Err(err) = Swarm::topology_mut(&mut self.swarm).flush_to_disk() { + 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", - Swarm::topology_mut(&mut self.swarm).num_peers()); - }, + self.swarm.num_topology_peers()); + } Ok(Async::Ready(None)) => { warn!(target: "sub-libp2p", "Topology flush stream ended unexpectedly"); return Ok(Async::Ready(None)) @@ -457,7 +437,7 @@ impl Service { impl Drop for Service { fn drop(&mut self) { - if let Err(err) = Swarm::topology_mut(&mut self.swarm).flush_to_disk() { + if let Err(err) = self.swarm.flush_topology() { warn!(target: "sub-libp2p", "Failed to flush topology: {:?}", err); } } diff --git a/core/network-libp2p/tests/test.rs b/core/network-libp2p/tests/test.rs index 5ff4255965274..f0ba968f5deb9 100644 --- a/core/network-libp2p/tests/test.rs +++ b/core/network-libp2p/tests/test.rs @@ -124,7 +124,7 @@ fn two_nodes_transfer_lots_of_packets() { }); let combined = fut1.select(fut2).map_err(|(err, _)| err); - tokio::runtime::Runtime::new().unwrap().block_on_all(combined).unwrap(); + tokio::runtime::Runtime::new().unwrap().block_on(combined).unwrap(); } #[test] diff --git a/core/primitives/Cargo.toml b/core/primitives/Cargo.toml index d3f1a59172732..38ee63ca75923 100644 --- a/core/primitives/Cargo.toml +++ b/core/primitives/Cargo.toml @@ -17,7 +17,7 @@ impl-serde = { version = "0.1", optional = true } wasmi = { version = "0.4.3", optional = true } hash-db = { version = "0.9", default-features = false } hash256-std-hasher = { version = "0.9", default-features = false } -ring = { version = "0.13", optional = true } +ring = { version = "0.14", optional = true } untrusted = { version = "0.6", optional = true } hex-literal = { version = "0.1", optional = true } base58 = { version = "0.1", optional = true } diff --git a/core/primitives/src/ed25519.rs b/core/primitives/src/ed25519.rs index ba43be841bb5f..be4b2a0a79db4 100644 --- a/core/primitives/src/ed25519.rs +++ b/core/primitives/src/ed25519.rs @@ -20,7 +20,7 @@ use untrusted; use blake2_rfc; -use ring::{rand, signature}; +use ring::{rand, signature, signature::KeyPair}; use {hash::H512, Ed25519AuthorityId}; use base58::{ToBase58, FromBase58}; @@ -199,9 +199,11 @@ impl Pair { pub fn generate_with_pkcs8() -> (Self, [u8; PKCS_LEN]) { let rng = rand::SystemRandom::new(); let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).expect("system randomness is available; qed"); - let pair = Self::from_pkcs8(&pkcs8_bytes).expect("just-generated pkcs#8 data is valid; qed"); + let pair = Self::from_pkcs8(&pkcs8_bytes.as_ref()).expect("just-generated pkcs#8 data is valid; qed"); - (pair, pkcs8_bytes) + let mut out = [0; PKCS_LEN]; + out.copy_from_slice(pkcs8_bytes.as_ref()); + (pair, out) } /// Generate new secure (random) key pair. @@ -211,7 +213,7 @@ impl Pair { } /// Generate from pkcs#8 bytes. - pub fn from_pkcs8(pkcs8_bytes: &[u8]) -> Result { + pub fn from_pkcs8(pkcs8_bytes: &[u8]) -> Result { signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).map(Pair) } @@ -234,7 +236,7 @@ impl Pair { /// Get the public key. pub fn public(&self) -> Public { let mut r = [0u8; 32]; - let pk = self.0.public_key_bytes(); + let pk = self.0.public_key().as_ref(); r.copy_from_slice(pk); Public(r) } From a3eba3ab4f2ada30ca39d1a89953f9b0bf8ea9cb Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Thu, 31 Jan 2019 16:34:42 +0100 Subject: [PATCH 02/18] Some more diagnostics --- core/network-libp2p/src/behaviour.rs | 4 ++++ core/network-libp2p/src/custom_proto/handler.rs | 2 +- core/network-libp2p/tests/test.rs | 11 +++++++---- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/core/network-libp2p/src/behaviour.rs b/core/network-libp2p/src/behaviour.rs index 5011a8a3c14ca..a8ffeaaeb6710 100644 --- a/core/network-libp2p/src/behaviour.rs +++ b/core/network-libp2p/src/behaviour.rs @@ -238,6 +238,10 @@ impl NetworkBehaviourEventProcess for Behaviour {} + Some(ServiceEvent::ClosedCustomProtocol { .. }) => { + // Only remove 1 if we haven't returned success yet, otherwise we + // will succeed the test multiple times. + if num_connecs < NUM_NODES - 1 { + num_connecs -= 1; + } + } _ => panic!(), } } From dd7468b27a73cc39a248021c9046004443f94dc7 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Thu, 31 Jan 2019 16:35:22 +0100 Subject: [PATCH 03/18] 30 seconds back to 5 seconds --- core/network-libp2p/src/custom_proto/handler.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/network-libp2p/src/custom_proto/handler.rs b/core/network-libp2p/src/custom_proto/handler.rs index be7419d91659b..749259dcb3e6d 100644 --- a/core/network-libp2p/src/custom_proto/handler.rs +++ b/core/network-libp2p/src/custom_proto/handler.rs @@ -135,7 +135,7 @@ where CustomProtosHandler { protocols, // We keep the connection alive for at least 5 seconds, waiting for what happens. - keep_alive: KeepAlive::Until(Instant::now() + Duration::from_secs(30)), + keep_alive: KeepAlive::Until(Instant::now() + Duration::from_secs(5)), state: State::Disabled, substreams: SmallVec::new(), events_queue: SmallVec::new(), From 5b0130c8033cef24f046f7bfcccd2a252d79a350 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Fri, 1 Feb 2019 16:05:35 +0100 Subject: [PATCH 04/18] Bump libp2p-core and improve test --- Cargo.lock | 7 ++++--- core/network-libp2p/Cargo.toml | 1 + core/network-libp2p/tests/test.rs | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9b83987a357e7..71d9813b7ee09 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2409,7 +2409,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2438,7 +2438,7 @@ name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2486,7 +2486,7 @@ name = "rand_xorshift" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3797,6 +3797,7 @@ name = "substrate-network-libp2p" version = "0.1.0" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/core/network-libp2p/Cargo.toml b/core/network-libp2p/Cargo.toml index e8f0f97d25662..b386addde5b0c 100644 --- a/core/network-libp2p/Cargo.toml +++ b/core/network-libp2p/Cargo.toml @@ -10,6 +10,7 @@ authors = ["Parity Technologies "] [dependencies] bytes = "0.4" error-chain = { version = "0.12", default-features = false } +env_logger = "0.6" fnv = "1.0" futures = "0.1" libp2p = { version = "0.3.0", default-features = false, features = ["secio-secp256k1", "libp2p-websocket"] } diff --git a/core/network-libp2p/tests/test.rs b/core/network-libp2p/tests/test.rs index 0fc2b01964330..a3b227bcfc131 100644 --- a/core/network-libp2p/tests/test.rs +++ b/core/network-libp2p/tests/test.rs @@ -129,6 +129,7 @@ fn two_nodes_transfer_lots_of_packets() { #[test] fn many_nodes_connectivity() { + env_logger::init(); // Creates many nodes, then make sure that they are all connected to each other. // Note: if you increase this number, keep in mind that there's a limit to the number of // simultaneous connections which will make the test fail if it is reached. This can be From 9b55a12a02f55667bc5869f63eaa851964fb39d8 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sun, 3 Feb 2019 13:50:22 +0100 Subject: [PATCH 05/18] Fix runtime Cargo.lock --- node/runtime/wasm/Cargo.lock | 63 ++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/node/runtime/wasm/Cargo.lock b/node/runtime/wasm/Cargo.lock index 2ae5b0765e88f..b2a50256bfe25 100644 --- a/node/runtime/wasm/Cargo.lock +++ b/node/runtime/wasm/Cargo.lock @@ -20,7 +20,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -30,8 +30,8 @@ name = "backtrace-sys" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -83,7 +83,7 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.25" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -209,7 +209,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -361,7 +361,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -405,7 +405,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.44" +version = "0.2.48" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -498,7 +498,7 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -523,7 +523,7 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -544,7 +544,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -629,7 +629,7 @@ name = "num_cpus" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -646,7 +646,7 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -655,8 +655,8 @@ name = "openssl-sys" version = "0.9.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -724,7 +724,7 @@ name = "parking_lot_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -736,7 +736,7 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -839,7 +839,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -850,7 +850,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -862,7 +862,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -935,12 +935,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ring" -version = "0.13.5" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1084,6 +1085,11 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "spin" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "sr-api-macros" version = "0.1.0" @@ -1647,7 +1653,7 @@ dependencies = [ "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1734,7 +1740,7 @@ name = "time" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1893,7 +1899,7 @@ 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)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2074,7 +2080,7 @@ dependencies = [ "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" -"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" +"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" @@ -2118,7 +2124,7 @@ dependencies = [ "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311" +"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" "checksum libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "688e8d65e495567c2c35ea0001b26b9debf0b4ea11f8cccc954233b75fc3428a" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" @@ -2172,7 +2178,7 @@ dependencies = [ "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" "checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" -"checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a" +"checksum ring 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)" = "148fc853f6d85f53f5f315d46701eaacc565cdfb3cb1959730c96e81e7e49999" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" @@ -2192,6 +2198,7 @@ dependencies = [ "checksum slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" "checksum slog-scope 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "053344c94c0e2b22da6305efddb698d7c485809427cf40555dc936085f67a9df" "checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" +"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" "checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" From 3a22d9ac530b68ecc34e2406bd324942f32d10dd Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Mon, 4 Feb 2019 14:18:15 +0100 Subject: [PATCH 06/18] More work --- core/network-libp2p/src/behaviour.rs | 4 +++ .../src/custom_proto/behaviour.rs | 12 ++++----- .../src/custom_proto/topology.rs | 26 +++++++++---------- core/network-libp2p/src/service_task.rs | 5 ++++ 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/core/network-libp2p/src/behaviour.rs b/core/network-libp2p/src/behaviour.rs index a8ffeaaeb6710..dd9beb8eba9ac 100644 --- a/core/network-libp2p/src/behaviour.rs +++ b/core/network-libp2p/src/behaviour.rs @@ -338,6 +338,10 @@ where NetworkBehaviour::inject_disconnected(&mut self.kademlia, peer_id, endpoint) } + fn inject_replaced(&mut self, peer_id: PeerId, closed: ConnectedPoint, opened: ConnectedPoint) { + NetworkBehaviour::inject_replaced(&mut self.kademlia, peer_id, closed, opened) + } + fn inject_node_event( &mut self, peer_id: PeerId, diff --git a/core/network-libp2p/src/custom_proto/behaviour.rs b/core/network-libp2p/src/custom_proto/behaviour.rs index ba38442eb2ed5..7f397c1aab265 100644 --- a/core/network-libp2p/src/custom_proto/behaviour.rs +++ b/core/network-libp2p/src/custom_proto/behaviour.rs @@ -140,9 +140,6 @@ impl CustomProtos { NetTopology::memory(local_peer_id.clone()) }; - // Register the external addresses provided by the user as our own. - topology.add_external_addrs(config.public_addresses.clone().into_iter()); - // Add the bootstrap nodes to the topology. for bootnode in config.boot_nodes.iter() { if let Ok((peer_id, addr)) = parse_str_addr(bootnode) { @@ -342,6 +339,7 @@ impl CustomProtos { if let Some((_, ban_end)) = self.banned_peers.iter().find(|(p, _)| p == peer_id) { if *ban_end > Instant::now() { + println!("banned peer"); continue } } @@ -351,7 +349,7 @@ impl CustomProtos { } // Next round is when we expect the topology will change. - self.next_connect_to_nodes.reset(will_change); + self.next_connect_to_nodes.reset(std::cmp::min(will_change, Instant::now() + Duration::from_secs(5))); } } @@ -453,11 +451,11 @@ where }; self.events.push(NetworkBehaviourAction::GenerateEvent(event)); - - // Trigger a `connect_to_nodes` round. - self.next_connect_to_nodes = Delay::new(Instant::now()); } + // Trigger a `connect_to_nodes` round. + self.next_connect_to_nodes = Delay::new(Instant::now()); + self.enabled_peers.remove(peer_id); } diff --git a/core/network-libp2p/src/custom_proto/topology.rs b/core/network-libp2p/src/custom_proto/topology.rs index f033f5a632cc4..cf04c0e5727f2 100644 --- a/core/network-libp2p/src/custom_proto/topology.rs +++ b/core/network-libp2p/src/custom_proto/topology.rs @@ -65,8 +65,6 @@ pub struct NetTopology { cache_path: Option, /// PeerId of the local node. local_peer_id: PeerId, - /// Known addresses for the local node to report to the network. - external_addresses: Vec, } impl NetTopology { @@ -79,7 +77,6 @@ impl NetTopology { store: Default::default(), cache_path: None, local_peer_id, - external_addresses: Vec::new(), } } @@ -97,7 +94,6 @@ impl NetTopology { store, cache_path: Some(path.to_owned()), local_peer_id, - external_addresses: Vec::new(), } } @@ -136,12 +132,6 @@ impl NetTopology { }); } - /// Add the external addresses that are known for the local node. - pub fn add_external_addrs(&mut self, addrs: TIter) - where TIter: Iterator { - self.external_addresses.extend(addrs); - } - /// Returns a list of all the known addresses of peers, ordered by the /// order in which we should attempt to connect to them. /// @@ -190,6 +180,10 @@ impl NetTopology { /// /// 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(); @@ -235,6 +229,10 @@ impl NetTopology { addrs: I, ) -> bool where I: Iterator { + if *peer_id == self.local_peer_id { + return false + } + let mut addrs: Vec<_> = addrs.collect(); let now_systime = SystemTime::now(); let now = Instant::now(); @@ -303,10 +301,6 @@ impl NetTopology { /// Returns the addresses stored for a specific peer. #[inline] pub fn addresses_of_peer(&mut self, peer: &PeerId) -> Vec { - if peer == &self.local_peer_id { - return self.external_addresses.clone() - } - let peer = if let Some(peer) = self.store.get_mut(peer) { peer } else { @@ -331,6 +325,10 @@ impl NetTopology { /// 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 diff --git a/core/network-libp2p/src/service_task.rs b/core/network-libp2p/src/service_task.rs index 5d3ec6545dd41..8e1e3ecacb49c 100644 --- a/core/network-libp2p/src/service_task.rs +++ b/core/network-libp2p/src/service_task.rs @@ -73,6 +73,11 @@ where TProtos: IntoIterator { } } + // Add external addresses. + for addr in &config.public_addresses { + Swarm::add_external_address(addr.clone()); + } + // Connect to the bootnodes. for bootnode in config.boot_nodes.iter() { match parse_str_addr(bootnode) { From f3b6cff7eab6778b291bd710eb8463633703dd31 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Mon, 4 Feb 2019 15:58:23 +0100 Subject: [PATCH 07/18] Finish upgrade to libp2p 0.3 --- Cargo.lock | 56 +++++++++---------- core/network-libp2p/Cargo.toml | 2 +- .../src/custom_proto/behaviour.rs | 25 +++++++-- .../src/custom_proto/topology.rs | 17 ++++-- core/network-libp2p/src/service_task.rs | 4 +- 5 files changed, 62 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 71d9813b7ee09..033791f3d919b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1305,13 +1305,13 @@ dependencies = [ [[package]] name = "libp2p" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" 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)", - "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core-derive 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "libp2p-dns 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libp2p-floodsub 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libp2p-identify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1337,7 +1337,7 @@ dependencies = [ [[package]] name = "libp2p-core" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1362,7 +1362,7 @@ dependencies = [ [[package]] name = "libp2p-core-derive" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1375,7 +1375,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1392,7 +1392,7 @@ dependencies = [ "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.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.2 (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)", "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1409,7 +1409,7 @@ 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.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1433,7 +1433,7 @@ 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.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "libp2p-identify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libp2p-ping 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1458,7 +1458,7 @@ 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.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "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.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1479,7 +1479,7 @@ 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.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "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)", @@ -1495,7 +1495,7 @@ 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.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "snow 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1510,7 +1510,7 @@ 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.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1527,7 +1527,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1538,7 +1538,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" 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.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "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)", @@ -1557,7 +1557,7 @@ dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "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)", @@ -1577,7 +1577,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1591,7 +1591,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1603,7 +1603,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rw-stream-sink 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1618,7 +1618,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "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.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2409,7 +2409,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2438,7 +2438,7 @@ name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2486,7 +2486,7 @@ name = "rand_xorshift" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3802,7 +3802,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.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "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)", @@ -4484,7 +4484,7 @@ name = "twox-hash" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4972,9 +4972,9 @@ dependencies = [ "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.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3462538e41bc5ebd047ce06948aaeaffb19f5106d3972a1a9f4a8bddf632503" -"checksum libp2p-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a318966714e3932b6760fc0a4222bb18759b1145f23288839f907d6de39408a3" -"checksum libp2p-core-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d4a19eddef3a04798b4f7aa210c53f300390a1c1d409eee5261628abd1d5ef6" +"checksum libp2p 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1cd53656209acc649a3aa4d9ce3580dd75d016317126fbdc6f8a8956f15f74de" +"checksum libp2p-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2fe63872c7526fbaf688afb39f0924111d512aae5e686791a317898aa48b4240" +"checksum libp2p-core-derive 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "040ed14400a3640ef060734f5ac5f7b6691902d962f7a65a28a883db99be6092" "checksum libp2p-dns 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a822c32da15ab0c4451792a4b000c37fbf8e3bc5ac471632f0b1f13e8e555524" "checksum libp2p-floodsub 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4380fbc42ec03251c9e9a4656744e8e88bbe59cbf4e084fa66370ed0b868d085" "checksum libp2p-identify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "583eb9c0ee46457e1dfe3495a0a306467ee7ab287d17e19fda392106acc8f166" diff --git a/core/network-libp2p/Cargo.toml b/core/network-libp2p/Cargo.toml index b386addde5b0c..903efc317489e 100644 --- a/core/network-libp2p/Cargo.toml +++ b/core/network-libp2p/Cargo.toml @@ -13,7 +13,7 @@ error-chain = { version = "0.12", default-features = false } env_logger = "0.6" fnv = "1.0" futures = "0.1" -libp2p = { version = "0.3.0", default-features = false, features = ["secio-secp256k1", "libp2p-websocket"] } +libp2p = { version = "0.3.1", default-features = false, features = ["secio-secp256k1", "libp2p-websocket"] } parking_lot = "0.7.1" lazy_static = "1.2" log = "0.4" diff --git a/core/network-libp2p/src/custom_proto/behaviour.rs b/core/network-libp2p/src/custom_proto/behaviour.rs index 7f397c1aab265..8827a4a8bf72f 100644 --- a/core/network-libp2p/src/custom_proto/behaviour.rs +++ b/core/network-libp2p/src/custom_proto/behaviour.rs @@ -63,6 +63,9 @@ pub struct CustomProtos { /// If true, only reserved peers can connect. reserved_only: bool, + /// List of the IDs of the peers we are connected to. + connected_peers: FnvHashSet, + /// List of the IDs of the reserved peers. We always try to maintain a connection these peers. reserved_peers: FnvHashSet, @@ -164,6 +167,7 @@ impl CustomProtos { max_incoming_connections, max_outgoing_connections, reserved_only: config.non_reserved_mode == NonReservedPeerMode::Deny, + connected_peers: Default::default(), reserved_peers: Default::default(), banned_peers: Vec::new(), open_protocols: Vec::with_capacity(open_protos_cap), @@ -339,7 +343,6 @@ impl CustomProtos { if let Some((_, ban_end)) = self.banned_peers.iter().find(|(p, _)| p == peer_id) { if *ban_end > Instant::now() { - println!("banned peer"); continue } } @@ -349,7 +352,7 @@ impl CustomProtos { } // Next round is when we expect the topology will change. - self.next_connect_to_nodes.reset(std::cmp::min(will_change, Instant::now() + Duration::from_secs(5))); + self.next_connect_to_nodes.reset(will_change); } } @@ -372,6 +375,8 @@ where // When a peer connects, its handler is initially in the disabled state. We make sure that // the peer is allowed, and if so we put it in the enabled state. + self.connected_peers.insert(peer_id.clone()); + let is_reserved = self.reserved_peers.contains(&peer_id); if self.reserved_only && !is_reserved { debug!(target: "sub-libp2p", "Ignoring {:?} because we're in reserved mode", peer_id); @@ -439,6 +444,9 @@ where } fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) { + let was_connected = self.connected_peers.remove(&peer_id); + debug_assert!(was_connected); + self.topology.set_disconnected(peer_id, &endpoint); while let Some(pos) = self.open_protocols.iter().position(|(p, _)| p == peer_id) { @@ -460,10 +468,15 @@ where } fn inject_dial_failure(&mut self, peer_id: Option<&PeerId>, addr: &Multiaddr, error: &dyn error::Error) { - debug!(target: "sub-libp2p", "Failed to reach peer {:?} through {} => {:?}", peer_id, addr, error); - self.topology.set_unreachable(addr); - // Trigger a `connect_to_nodes` round. - self.next_connect_to_nodes = Delay::new(Instant::now()); + if let Some(peer_id) = peer_id.as_ref() { + debug!(target: "sub-libp2p", "Failed to reach peer {:?} through {} => {:?}", peer_id, addr, error); + if self.connected_peers.contains(peer_id) { + self.topology.set_unreachable(addr); + } + + // Trigger a `connect_to_nodes` round. + self.next_connect_to_nodes = Delay::new(Instant::now()); + } } fn inject_node_event( diff --git a/core/network-libp2p/src/custom_proto/topology.rs b/core/network-libp2p/src/custom_proto/topology.rs index cf04c0e5727f2..6bc10eeea892f 100644 --- a/core/network-libp2p/src/custom_proto/topology.rs +++ b/core/network-libp2p/src/custom_proto/topology.rs @@ -234,6 +234,7 @@ impl NetTopology { } let mut addrs: Vec<_> = addrs.collect(); + let now_systime = SystemTime::now(); let now = Instant::now(); @@ -241,14 +242,14 @@ impl NetTopology { let new_addrs = peer.addrs .drain(..) - .filter_map(|a| { + .filter(|a| { if a.expires < now_systime && !a.is_connected() { - return None + return false } - if let Some(pos) = addrs.iter().position(|&(ref addr, _)| addr == &a.addr) { + while let Some(pos) = addrs.iter().position(|&(ref addr, _)| addr == &a.addr) { addrs.remove(pos); } - Some(a) + true }) .collect(); peer.addrs = new_addrs; @@ -256,6 +257,7 @@ impl NetTopology { let mut anything_changed = false; if !addrs.is_empty() { + anything_changed = true; trace!( target: "sub-libp2p", "Peer store: adding addresses {:?} for {:?}", @@ -281,7 +283,11 @@ impl NetTopology { } } - anything_changed = true; + // `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, @@ -406,6 +412,7 @@ impl NetTopology { continue } + debug_assert!(!a.is_connected()); 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; diff --git a/core/network-libp2p/src/service_task.rs b/core/network-libp2p/src/service_task.rs index 8e1e3ecacb49c..871735aaac787 100644 --- a/core/network-libp2p/src/service_task.rs +++ b/core/network-libp2p/src/service_task.rs @@ -73,10 +73,10 @@ where TProtos: IntoIterator { } } - // Add external addresses. + /*// Add external addresses. for addr in &config.public_addresses { Swarm::add_external_address(addr.clone()); - } + }*/ // Connect to the bootnodes. for bootnode in config.boot_nodes.iter() { From 5e45c03e042390c7e2ffd91457a355d99ff0bab0 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Mon, 4 Feb 2019 16:19:36 +0100 Subject: [PATCH 08/18] Add a maximum of 60 seconds for the rounds --- core/network-libp2p/src/custom_proto/behaviour.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/network-libp2p/src/custom_proto/behaviour.rs b/core/network-libp2p/src/custom_proto/behaviour.rs index 8827a4a8bf72f..888a4cb5b4d2a 100644 --- a/core/network-libp2p/src/custom_proto/behaviour.rs +++ b/core/network-libp2p/src/custom_proto/behaviour.rs @@ -26,7 +26,7 @@ use libp2p::core::swarm::{ConnectedPoint, NetworkBehaviour, NetworkBehaviourActi use libp2p::core::{protocols_handler::ProtocolsHandler, Multiaddr, PeerId}; use log::{debug, trace, warn}; use smallvec::SmallVec; -use std::{error, io, marker::PhantomData, path::Path, time::Duration, time::Instant}; +use std::{cmp, error, io, marker::PhantomData, path::Path, time::Duration, time::Instant}; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_timer::Delay; @@ -352,7 +352,7 @@ impl CustomProtos { } // Next round is when we expect the topology will change. - self.next_connect_to_nodes.reset(will_change); + self.next_connect_to_nodes.reset(cmp::min(will_change, Instant::now() + Duration::from_secs(60))); } } From 4f51dffd7a07b587fe5bf9f83a1705042f469b05 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Mon, 4 Feb 2019 18:39:33 +0100 Subject: [PATCH 09/18] Remove env_logger --- Cargo.lock | 1 - core/network-libp2p/Cargo.toml | 1 - core/network-libp2p/tests/test.rs | 1 - 3 files changed, 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 033791f3d919b..f1068f06d630f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3797,7 +3797,6 @@ name = "substrate-network-libp2p" version = "0.1.0" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/core/network-libp2p/Cargo.toml b/core/network-libp2p/Cargo.toml index 903efc317489e..3fae20f23a7a4 100644 --- a/core/network-libp2p/Cargo.toml +++ b/core/network-libp2p/Cargo.toml @@ -10,7 +10,6 @@ authors = ["Parity Technologies "] [dependencies] bytes = "0.4" error-chain = { version = "0.12", default-features = false } -env_logger = "0.6" fnv = "1.0" futures = "0.1" libp2p = { version = "0.3.1", default-features = false, features = ["secio-secp256k1", "libp2p-websocket"] } diff --git a/core/network-libp2p/tests/test.rs b/core/network-libp2p/tests/test.rs index a3b227bcfc131..0fc2b01964330 100644 --- a/core/network-libp2p/tests/test.rs +++ b/core/network-libp2p/tests/test.rs @@ -129,7 +129,6 @@ fn two_nodes_transfer_lots_of_packets() { #[test] fn many_nodes_connectivity() { - env_logger::init(); // Creates many nodes, then make sure that they are all connected to each other. // Note: if you increase this number, keep in mind that there's a limit to the number of // simultaneous connections which will make the test fail if it is reached. This can be From 1e4e68477f20aa6adff815cc4ef0c9aabef9028c Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Tue, 5 Feb 2019 11:17:55 +0100 Subject: [PATCH 10/18] Update Cargo.lock --- node/runtime/wasm/Cargo.lock | 22 +++++++++++++----- .../release/node_runtime.compact.wasm | Bin 836511 -> 842397 bytes 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/node/runtime/wasm/Cargo.lock b/node/runtime/wasm/Cargo.lock index b2a50256bfe25..13c3df27c24fe 100644 --- a/node/runtime/wasm/Cargo.lock +++ b/node/runtime/wasm/Cargo.lock @@ -30,7 +30,7 @@ name = "backtrace-sys" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -83,7 +83,7 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.28" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -655,7 +655,7 @@ name = "openssl-sys" version = "0.9.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -938,7 +938,7 @@ name = "ring" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1404,6 +1404,7 @@ dependencies = [ "mashup 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1589,7 +1590,6 @@ version = "0.1.0" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1599,6 +1599,7 @@ dependencies = [ "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-version 0.1.0", + "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", "substrate-serializer 0.1.0", "substrate-state-machine 0.1.0", @@ -1639,6 +1640,14 @@ dependencies = [ "substrate-primitives 0.1.0", ] +[[package]] +name = "substrate-panic-handler" +version = "0.1.0" +dependencies = [ + "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "substrate-primitives" version = "0.1.0" @@ -1681,6 +1690,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", "substrate-trie 0.4.0", "trie-db 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2080,7 +2090,7 @@ dependencies = [ "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" -"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" +"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" diff --git a/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm b/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm index 151d49c6a3b5b9230ae67cee65e5b43d817cbe7c..05045dab485b8c26c9ec3c4e6f27b893df5a71cc 100644 GIT binary patch delta 103890 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

YWFuBW+qRgkTZxI`ZFY2}G8RHo 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�(#L(Q%^Frs17VR(OHviPuilMK>Y5(&+BBrGp$g~iIz9n94T3eXXmF;xBPaeW}m!0!g$8EL=@ex0>;a*y#}e6kryTiG!3QqQH&bq|f&8^VDB%f6xn0 zzH0QQ?CI-2!Cu|j)wl4P(Vy<=Sz>xmSlk<}8U3lAp1vjX`S=yL_7x$!sE;Dgp!89a z;=zr|-TjJ~GGPf6rDt%SHv#E0gGrH-Qc8o7z0Sq2iX*q!@Vn{V2zABOKu!(AUH%Vu C<&&2H From 3e72783a7540e6588cb204966e7e4889ec82e2b1 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Tue, 5 Feb 2019 11:29:59 +0100 Subject: [PATCH 11/18] Update Cargo.lock in test-runtime --- core/test-runtime/wasm/Cargo.lock | 75 +++++++++++------- .../substrate_test_runtime.compact.wasm | Bin 59955 -> 60414 bytes 2 files changed, 46 insertions(+), 29 deletions(-) diff --git a/core/test-runtime/wasm/Cargo.lock b/core/test-runtime/wasm/Cargo.lock index a3e0483baac28..ea42c63ff2275 100644 --- a/core/test-runtime/wasm/Cargo.lock +++ b/core/test-runtime/wasm/Cargo.lock @@ -20,7 +20,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -30,8 +30,8 @@ name = "backtrace-sys" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -83,7 +83,7 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.25" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -209,7 +209,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -361,7 +361,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -405,7 +405,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.44" +version = "0.2.48" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -498,7 +498,7 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -523,7 +523,7 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -544,7 +544,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -571,7 +571,7 @@ name = "num_cpus" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -588,7 +588,7 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -597,8 +597,8 @@ name = "openssl-sys" version = "0.9.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -666,7 +666,7 @@ name = "parking_lot_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -678,7 +678,7 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -771,7 +771,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -782,7 +782,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -794,7 +794,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -867,12 +867,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ring" -version = "0.13.5" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1008,6 +1009,11 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "spin" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "sr-api-macros" version = "0.1.0" @@ -1090,6 +1096,7 @@ dependencies = [ "mashup 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1206,7 +1213,6 @@ version = "0.1.0" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1216,6 +1222,7 @@ dependencies = [ "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-version 0.1.0", + "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", "substrate-serializer 0.1.0", "substrate-state-machine 0.1.0", @@ -1244,6 +1251,14 @@ dependencies = [ "substrate-primitives 0.1.0", ] +[[package]] +name = "substrate-panic-handler" +version = "0.1.0" +dependencies = [ + "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "substrate-primitives" version = "0.1.0" @@ -1258,7 +1273,7 @@ dependencies = [ "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1286,6 +1301,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", "substrate-trie 0.4.0", "trie-db 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1374,7 +1390,7 @@ name = "time" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1533,7 +1549,7 @@ 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)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1714,7 +1730,7 @@ dependencies = [ "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" -"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" +"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" @@ -1758,7 +1774,7 @@ dependencies = [ "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311" +"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" "checksum libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "688e8d65e495567c2c35ea0001b26b9debf0b4ea11f8cccc954233b75fc3428a" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" @@ -1811,7 +1827,7 @@ dependencies = [ "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" "checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" -"checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a" +"checksum ring 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)" = "148fc853f6d85f53f5f315d46701eaacc565cdfb3cb1959730c96e81e7e49999" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" @@ -1830,6 +1846,7 @@ dependencies = [ "checksum slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" "checksum slog-scope 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "053344c94c0e2b22da6305efddb698d7c485809427cf40555dc936085f67a9df" "checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" +"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" "checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" diff --git a/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm b/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm index ec7eee0dddf8d642f6e24303c2104ac8c4217dea..c49dbf08c49f354c5d9114b861a9cecdfbfe8aa2 100644 GIT binary patch delta 11916 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 Vjlk@|RwWb&CRzf)mSD8`{{rFVT0H;& delta 11327 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 Z)7ixk(**Q07EuE}f2`i;uMY%j{|{lP5UT(H From 30289d70ee1f56cca460d0fb5ac35d2e933e2a80 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Tue, 5 Feb 2019 11:45:08 +0100 Subject: [PATCH 12/18] Fix test compilation --- core/keystore/src/lib.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/core/keystore/src/lib.rs b/core/keystore/src/lib.rs index ed311d1653357..98bddb70742a8 100644 --- a/core/keystore/src/lib.rs +++ b/core/keystore/src/lib.rs @@ -230,7 +230,7 @@ mod tests { #[test] fn encrypt_and_decrypt() { let plain = [1; PKCS_LEN]; - let encrypted_key = EncryptedKey::encrypt(&plain, "thepassword", KEY_ITERATIONS as u32); + let encrypted_key = EncryptedKey::encrypt(&plain, "thepassword", NonZeroU32::new(KEY_ITERATIONS as u32).expect("KEY_ITERATIONS is not zero; QED")); let decrypted_key = encrypted_key.decrypt("thepassword").unwrap(); @@ -240,7 +240,11 @@ mod tests { #[test] fn decrypt_wrong_password_fails() { let plain = [1; PKCS_LEN]; - let encrypted_key = EncryptedKey::encrypt(&plain, "thepassword", KEY_ITERATIONS as u32); + let encrypted_key = EncryptedKey::encrypt( + &plain, + "thepassword", + NonZeroU32::new(KEY_ITERATIONS as u32).expect("KEY_ITERATIONS is not zero; QED") + ); assert!(encrypted_key.decrypt("thepassword2").is_err()); } @@ -248,9 +252,13 @@ mod tests { #[test] fn decrypt_wrong_iterations_fails() { let plain = [1; PKCS_LEN]; - let mut encrypted_key = EncryptedKey::encrypt(&plain, "thepassword", KEY_ITERATIONS as u32); + let mut encrypted_key = EncryptedKey::encrypt( + &plain, + "thepassword", + NonZeroU32::new(KEY_ITERATIONS as u32).expect("KEY_ITERATIONS is not zero; QED") + ); - encrypted_key.iterations -= 64; + encrypted_key.iterations = NonZeroU32::new(encrypted_key.iterations.get() - 64).unwrap(); assert!(encrypted_key.decrypt("thepassword").is_err()); } From e7016166f0f101add6aa99968d3bf2bafaf6592c Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Tue, 5 Feb 2019 16:04:04 +0100 Subject: [PATCH 13/18] Make the test pass --- .../network-libp2p/src/custom_proto/handler.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/core/network-libp2p/src/custom_proto/handler.rs b/core/network-libp2p/src/custom_proto/handler.rs index 749259dcb3e6d..28211284885dd 100644 --- a/core/network-libp2p/src/custom_proto/handler.rs +++ b/core/network-libp2p/src/custom_proto/handler.rs @@ -19,7 +19,7 @@ use crate::custom_proto::upgrade::{RegisteredProtocol, RegisteredProtocols, Regi use bytes::Bytes; use futures::prelude::*; use libp2p::core::{ - Endpoint, ProtocolsHandler, ProtocolsHandlerEvent, + ProtocolsHandler, ProtocolsHandlerEvent, protocols_handler::KeepAlive, protocols_handler::ProtocolsHandlerUpgrErr, upgrade::{InboundUpgrade, OutboundUpgrade} @@ -146,11 +146,17 @@ where fn inject_fully_negotiated( &mut self, proto: RegisteredProtocolSubstream, - _: Endpoint, ) { match self.state { - State::Disabled | State::ShuttingDown => return, - State::Normal => () + // TODO: Normally we should refuse incoming connections if we're disabled; however + // tests are failing if we do that because on localhost substreams arrive quicker than + // we receive the "Enabled" message from the network behaviour. Which fix to employ is + // kind of blurry. This problem will become irrelevant after + // https://github.com/paritytech/substrate/issues/1517 + // TODO: also, we should shut down refused substreams gracefully; this should be fixed + // at the same time as the todo above + State::ShuttingDown => return, + State::Disabled | State::Normal => () } if self.substreams.iter().any(|p| p.protocol_id() == proto.protocol_id()) { @@ -189,7 +195,7 @@ where &mut self, proto: >::Output ) { - self.inject_fully_negotiated(proto, Endpoint::Listener); + self.inject_fully_negotiated(proto); } #[inline] @@ -198,7 +204,7 @@ where proto: >::Output, _: Self::OutboundOpenInfo ) { - self.inject_fully_negotiated(proto, Endpoint::Dialer); + self.inject_fully_negotiated(proto); } fn inject_event(&mut self, message: CustomProtosHandlerIn) { From d1d1fc0469f286d65a41c6430654d98b0fff4cc4 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Tue, 5 Feb 2019 16:08:22 +0100 Subject: [PATCH 14/18] Add identify addresses to Kademlia --- core/network-libp2p/src/behaviour.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/network-libp2p/src/behaviour.rs b/core/network-libp2p/src/behaviour.rs index dd9beb8eba9ac..86207a8aba057 100644 --- a/core/network-libp2p/src/behaviour.rs +++ b/core/network-libp2p/src/behaviour.rs @@ -242,6 +242,9 @@ impl NetworkBehaviourEventProcess for Behaviour Date: Tue, 5 Feb 2019 16:19:41 +0100 Subject: [PATCH 15/18] Don't connect to nodes we're already connected to --- core/network-libp2p/src/custom_proto/behaviour.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/network-libp2p/src/custom_proto/behaviour.rs b/core/network-libp2p/src/custom_proto/behaviour.rs index 888a4cb5b4d2a..359e66c1ccfb2 100644 --- a/core/network-libp2p/src/custom_proto/behaviour.rs +++ b/core/network-libp2p/src/custom_proto/behaviour.rs @@ -341,6 +341,10 @@ impl CustomProtos { continue } + if self.connected_peers.contains(&peer_id) { + continue + } + if let Some((_, ban_end)) = self.banned_peers.iter().find(|(p, _)| p == peer_id) { if *ban_end > Instant::now() { continue From a149aac72b6bf7b2f7be7b53a24033f6a0f5d34d Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Wed, 6 Feb 2019 11:48:56 +0100 Subject: [PATCH 16/18] Add warning for non-Substrate nodes --- core/network-libp2p/src/behaviour.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/network-libp2p/src/behaviour.rs b/core/network-libp2p/src/behaviour.rs index 86207a8aba057..196c1fa9c4f25 100644 --- a/core/network-libp2p/src/behaviour.rs +++ b/core/network-libp2p/src/behaviour.rs @@ -238,6 +238,9 @@ impl NetworkBehaviourEventProcess for Behaviour Date: Wed, 6 Feb 2019 14:50:09 +0100 Subject: [PATCH 17/18] Fix external address not added --- core/network-libp2p/src/service_task.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/network-libp2p/src/service_task.rs b/core/network-libp2p/src/service_task.rs index 446e645088b6c..68959942d0768 100644 --- a/core/network-libp2p/src/service_task.rs +++ b/core/network-libp2p/src/service_task.rs @@ -73,10 +73,10 @@ where TProtos: IntoIterator { } } - /*// Add external addresses. + // Add external addresses. for addr in &config.public_addresses { - Swarm::add_external_address(addr.clone()); - }*/ + Swarm::add_external_address(&mut swarm, addr.clone()); + } // Connect to the bootnodes. for bootnode in config.boot_nodes.iter() { From ce0ccd3af9dad63945765acc63bec76c7021d01b Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Wed, 6 Feb 2019 15:03:39 +0100 Subject: [PATCH 18/18] Start in Enabled mode --- .../network-libp2p/src/custom_proto/behaviour.rs | 16 ++++++++++++++++ core/network-libp2p/src/custom_proto/handler.rs | 15 +++++---------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/core/network-libp2p/src/custom_proto/behaviour.rs b/core/network-libp2p/src/custom_proto/behaviour.rs index 359e66c1ccfb2..b7575524c1eb2 100644 --- a/core/network-libp2p/src/custom_proto/behaviour.rs +++ b/core/network-libp2p/src/custom_proto/behaviour.rs @@ -384,6 +384,10 @@ where let is_reserved = self.reserved_peers.contains(&peer_id); if self.reserved_only && !is_reserved { debug!(target: "sub-libp2p", "Ignoring {:?} because we're in reserved mode", peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtosHandlerIn::Disable, + }); return } @@ -392,6 +396,10 @@ where if let Some((_, expire)) = self.banned_peers.iter().find(|(p, _)| p == &peer_id) { if *expire >= Instant::now() { debug!(target: "sub-libp2p", "Ignoring banned peer {:?}", peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtosHandlerIn::Disable, + }); return } } @@ -407,6 +415,10 @@ where debug_assert!(num_outgoing <= self.max_outgoing_connections); if num_outgoing == self.max_outgoing_connections { + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtosHandlerIn::Disable, + }); return } } @@ -420,6 +432,10 @@ where if num_ingoing == self.max_incoming_connections { debug!(target: "sub-libp2p", "Ignoring incoming connection from {:?} because \ we're full", peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtosHandlerIn::Disable, + }); return } } diff --git a/core/network-libp2p/src/custom_proto/handler.rs b/core/network-libp2p/src/custom_proto/handler.rs index 28211284885dd..198e51d7d06d1 100644 --- a/core/network-libp2p/src/custom_proto/handler.rs +++ b/core/network-libp2p/src/custom_proto/handler.rs @@ -136,7 +136,7 @@ where protocols, // We keep the connection alive for at least 5 seconds, waiting for what happens. keep_alive: KeepAlive::Until(Instant::now() + Duration::from_secs(5)), - state: State::Disabled, + state: State::Normal, substreams: SmallVec::new(), events_queue: SmallVec::new(), } @@ -148,15 +148,10 @@ where proto: RegisteredProtocolSubstream, ) { match self.state { - // TODO: Normally we should refuse incoming connections if we're disabled; however - // tests are failing if we do that because on localhost substreams arrive quicker than - // we receive the "Enabled" message from the network behaviour. Which fix to employ is - // kind of blurry. This problem will become irrelevant after - // https://github.com/paritytech/substrate/issues/1517 - // TODO: also, we should shut down refused substreams gracefully; this should be fixed - // at the same time as the todo above - State::ShuttingDown => return, - State::Disabled | State::Normal => () + // TODO: we should shut down refused substreams gracefully; this should be fixed + // at the same time as https://github.com/paritytech/substrate/issues/1517 + State::Disabled | State::ShuttingDown => return, + State::Normal => () } if self.substreams.iter().any(|p| p.protocol_id() == proto.protocol_id()) {