From a94e7e7c1883bb2fcc6e074fe3d4212832667b26 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Tue, 22 May 2018 16:50:58 +0200 Subject: [PATCH] Switch from devp2p to libp2p --- Cargo.lock | 900 +++++++++++++++--- README.md | 3 +- substrate/network-libp2p/Cargo.toml | 30 + substrate/network-libp2p/src/custom_proto.rs | 270 ++++++ substrate/network-libp2p/src/lib.rs | 49 + substrate/network-libp2p/src/network_state.rs | 526 ++++++++++ substrate/network-libp2p/src/service.rs | 832 ++++++++++++++++ substrate/network-libp2p/src/timeouts.rs | 87 ++ substrate/network-libp2p/src/transport.rs | 37 + substrate/network-libp2p/tests/tests.rs | 151 +++ substrate/network/Cargo.toml | 2 +- substrate/network/src/lib.rs | 2 +- substrate/network/src/service.rs | 5 +- 13 files changed, 2747 insertions(+), 147 deletions(-) create mode 100644 substrate/network-libp2p/Cargo.toml create mode 100644 substrate/network-libp2p/src/custom_proto.rs create mode 100644 substrate/network-libp2p/src/lib.rs create mode 100644 substrate/network-libp2p/src/network_state.rs create mode 100644 substrate/network-libp2p/src/service.rs create mode 100644 substrate/network-libp2p/src/timeouts.rs create mode 100644 substrate/network-libp2p/src/transport.rs create mode 100644 substrate/network-libp2p/tests/tests.rs diff --git a/Cargo.lock b/Cargo.lock index 875610ebe07e5..101794a73df82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,6 +6,20 @@ dependencies = [ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "aio-limited" +version = "0.1.0" +source = "git+https://github.com/paritytech/aio-limited.git#1f42497dcd2a6f85b83af97cd80314b26a1e4a9e" +dependencies = [ + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ansi_term" version = "0.9.0" @@ -35,6 +49,11 @@ dependencies = [ "xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayref" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "arrayvec" version = "0.4.7" @@ -43,6 +62,14 @@ dependencies = [ "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "asn1_der" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "etrace 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "assert_matches" version = "1.2.0" @@ -79,6 +106,11 @@ dependencies = [ "libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "base-x" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "base58" version = "0.1.0" @@ -101,6 +133,15 @@ dependencies = [ "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "base64" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "base64" version = "0.9.1" @@ -110,6 +151,15 @@ dependencies = [ "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bigint" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bitflags" version = "0.9.1" @@ -129,6 +179,30 @@ dependencies = [ "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "block-buffer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bs58" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byte-tools" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.2.3" @@ -156,6 +230,15 @@ name = "cfg-if" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "chashmap" +version = "2.2.1" +source = "git+https://github.com/redox-os/tfs#3e7dcdb0c586d0d8bb3f25bfd948d2f418a4ab10" +dependencies = [ + "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "chrono" version = "0.4.2" @@ -166,6 +249,24 @@ dependencies = [ "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cid" +version = "0.2.3" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "integer-encoding 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "multibase 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "multihash 0.8.1-pre (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", +] + +[[package]] +name = "circular-buffer" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "smallvec 0.6.0 (git+https://github.com/Vurich/rust-smallvec.git?branch=array-zero)", +] + [[package]] name = "clap" version = "2.31.2" @@ -181,6 +282,14 @@ dependencies = [ "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cmake" version = "0.1.31" @@ -297,6 +406,19 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "datastore" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "chashmap 2.2.1 (git+https://github.com/redox-os/tfs)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "demo-cli" version = "0.1.0" @@ -393,6 +515,14 @@ name = "difference" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "digest" +version = "0.7.4" +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)", +] + [[package]] name = "dtoa" version = "0.4.2" @@ -441,6 +571,14 @@ dependencies = [ name = "environmental" version = "0.1.0" +[[package]] +name = "error-chain" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "error-chain" version = "0.12.0" @@ -496,7 +634,6 @@ dependencies = [ "crossbeam 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)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -536,41 +673,6 @@ dependencies = [ "snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)", ] -[[package]] -name = "ethcore-network-devp2p" -version = "1.12.0" -source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" -dependencies = [ - "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-bytes 0.1.0 (git+https://github.com/paritytech/parity.git)", - "ethcore-crypto 0.1.0 (git+https://github.com/paritytech/parity.git)", - "ethcore-io 1.12.0 (git+https://github.com/paritytech/parity.git)", - "ethcore-logger 1.12.0 (git+https://github.com/paritytech/parity.git)", - "ethcore-network 1.12.0 (git+https://github.com/paritytech/parity.git)", - "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethkey 0.3.0 (git+https://github.com/paritytech/parity.git)", - "igd 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipnetwork 0.12.8 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.2 (git+https://github.com/paritytech/parity.git)", - "libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "path 0.1.0 (git+https://github.com/paritytech/parity.git)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.2.1 (git+https://github.com/paritytech/parity.git)", - "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ethereum-types" version = "0.3.2" @@ -615,6 +717,11 @@ dependencies = [ "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "etrace" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "exit-future" version = "0.1.0" @@ -624,6 +731,11 @@ dependencies = [ "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fdlimit" version = "0.1.1" @@ -707,11 +819,28 @@ dependencies = [ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "futures-mutex" +version = "0.3.0" +source = "git+https://github.com/paritytech/futures-mutex#18ca11258512a1846826bc83782e538ac692d990" +dependencies = [ + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "gcc" version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "generic-array" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "getopts" version = "0.2.17" @@ -828,20 +957,9 @@ dependencies = [ ] [[package]] -name = "igd" -version = "0.7.0" +name = "integer-encoding" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.11.27 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-retry 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "xmltree 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "integer-sqrt" @@ -981,66 +1099,331 @@ dependencies = [ ] [[package]] -name = "kvdb" +name = "kvdb" +version = "0.1.0" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" +dependencies = [ + "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-bytes 0.1.0 (git+https://github.com/paritytech/parity.git)", +] + +[[package]] +name = "kvdb-memorydb" +version = "0.1.0" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" +dependencies = [ + "kvdb 0.1.0 (git+https://github.com/paritytech/parity.git)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "kvdb-rocksdb" +version = "0.1.0" +source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" +dependencies = [ + "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fs-swap 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb 0.1.0 (git+https://github.com/paritytech/parity.git)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "rocksdb 0.4.5 (git+https://github.com/paritytech/rust-rocksdb)", +] + +[[package]] +name = "language-tags" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazy_static" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazy_static" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazycell" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.41" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libp2p" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "libp2p-dns 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "libp2p-floodsub 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "libp2p-identify 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "libp2p-kad 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "libp2p-mplex 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "libp2p-ping 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "libp2p-ratelimit 0.1.1 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "libp2p-relay 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "libp2p-secio 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "libp2p-tcp-transport 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "libp2p-transport-timeout 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "libp2p-websocket 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "stdweb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-core" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "bs58 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "multihash 0.8.1-pre (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "multistream-select 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 1.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-dns" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "tokio-dns-unofficial 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-floodsub" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "bs58 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", +] + +[[package]] +name = "libp2p-identify" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf-codegen-pure 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", +] + +[[package]] +name = "libp2p-kad" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "bigint 4.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "datastore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "libp2p-identify 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "libp2p-ping 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", +] + +[[package]] +name = "libp2p-mplex" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "circular-buffer 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-mutex 0.3.0 (git+https://github.com/paritytech/futures-mutex)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", +] + +[[package]] +name = "libp2p-peerstore" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "bs58 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "datastore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-ping" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "multistream-select 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-ratelimit" +version = "0.1.1" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "aio-limited 0.1.0 (git+https://github.com/paritytech/aio-limited.git)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-relay" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "protobuf 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", +] + +[[package]] +name = "libp2p-secio" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "asn1_der 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf-codegen-pure 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-tcp-transport" version = "0.1.0" -source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" dependencies = [ - "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-bytes 0.1.0 (git+https://github.com/paritytech/parity.git)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "kvdb-memorydb" +name = "libp2p-transport-timeout" version = "0.1.0" -source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" dependencies = [ - "kvdb 0.1.0 (git+https://github.com/paritytech/parity.git)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "kvdb-rocksdb" +name = "libp2p-websocket" version = "0.1.0" -source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" dependencies = [ - "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fs-swap 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity.git)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "rocksdb 0.4.5 (git+https://github.com/paritytech/rust-rocksdb)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "rw-stream-sink 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "stdweb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "websocket 0.20.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazy_static" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazy_static" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazycell" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libc" -version = "0.2.41" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "linked-hash-map" version = "0.5.1" @@ -1168,6 +1551,47 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "multiaddr" +version = "0.3.0" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cid 0.2.3 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "integer-encoding 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "multibase" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base-x 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "multihash" +version = "0.8.1-pre" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "sha1 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "multistream-select" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", +] + [[package]] name = "native-tls" version = "0.1.5" @@ -1197,6 +1621,15 @@ name = "nodrop" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "num-bigint" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-integer" version = "0.1.38" @@ -1205,6 +1638,14 @@ dependencies = [ "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-traits" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-traits" version = "0.2.4" @@ -1324,11 +1765,6 @@ dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "path" -version = "0.1.0" -source = "git+https://github.com/paritytech/parity.git#4145be863bec10038fc0ac5d36a41365b5087344" - [[package]] name = "patricia-trie" version = "0.1.0" @@ -1624,6 +2060,33 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "protobuf" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "protobuf" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "protobuf-codegen" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "protobuf 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "protobuf-codegen-pure" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "protobuf 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf-codegen 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pulldown-cmark" version = "0.0.3" @@ -1687,6 +2150,23 @@ dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand" +version = "0.5.2" +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.41 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rayon" version = "0.8.2" @@ -1713,7 +2193,7 @@ dependencies = [ "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1860,6 +2340,16 @@ dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rw-stream-sink" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "safe-mix" version = "0.1.0" @@ -1954,6 +2444,22 @@ name = "sha1" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "sha1" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "sha2" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "shell32-sys" version = "0.1.2" @@ -1972,11 +2478,6 @@ dependencies = [ "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "slab" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "slab" version = "0.3.0" @@ -2033,6 +2534,16 @@ name = "smallvec" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "smallvec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "smallvec" +version = "0.6.0" +source = "git+https://github.com/Vurich/rust-smallvec.git?branch=array-zero#cccd87359f8b52b109e96abe3f94815c14b01a67" + [[package]] name = "smallvec" version = "0.6.1" @@ -2061,6 +2572,11 @@ name = "stable_deref_trait" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "stdweb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "strsim" version = "0.7.0" @@ -2226,7 +2742,6 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-io 1.12.0 (git+https://github.com/paritytech/parity.git)", "ethcore-network 1.12.0 (git+https://github.com/paritytech/parity.git)", - "ethcore-network-devp2p 1.12.0 (git+https://github.com/paritytech/parity.git)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2239,6 +2754,7 @@ dependencies = [ "substrate-client 0.1.0", "substrate-codec 0.1.0", "substrate-keyring 0.1.0", + "substrate-network-libp2p 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-primitives 0.1.0", "substrate-runtime-support 0.1.0", @@ -2247,6 +2763,28 @@ dependencies = [ "substrate-test-client 0.1.0", ] +[[package]] +name = "substrate-network-libp2p" +version = "0.1.0" +dependencies = [ + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-bytes 0.1.0 (git+https://github.com/paritytech/parity.git)", + "ethcore-io 1.12.0 (git+https://github.com/paritytech/parity.git)", + "ethcore-logger 1.12.0 (git+https://github.com/paritytech/parity.git)", + "ethcore-network 1.12.0 (git+https://github.com/paritytech/parity.git)", + "ethkey 0.3.0 (git+https://github.com/paritytech/parity.git)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "varint 0.1.0 (git+https://github.com/libp2p/rust-libp2p)", +] + [[package]] name = "substrate-primitives" version = "0.1.0" @@ -2638,6 +3176,18 @@ dependencies = [ "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tempfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "termion" version = "1.5.1" @@ -2726,6 +3276,17 @@ dependencies = [ "tokio-timer 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-dns-unofficial" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-executor" version = "0.1.2" @@ -2784,17 +3345,6 @@ dependencies = [ "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "tokio-retry" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "tokio-service" version = "0.1.0" @@ -2935,6 +3485,11 @@ name = "typeable" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "typenum" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ucd-util" version = "0.1.1" @@ -3028,6 +3583,32 @@ name = "utf8-ranges" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "varint" +version = "0.1.0" +source = "git+https://github.com/libp2p/rust-libp2p#143a1845b148fbe7145773d42615301d36ef8338" +dependencies = [ + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "varint" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8#322769ee562442215518e4fcfdb727a5dd971bc8" +dependencies = [ + "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "vcpkg" version = "0.2.3" @@ -3169,22 +3750,6 @@ name = "xdg" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "xml-rs" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "xmltree" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "yaml-rust" version = "0.3.5" @@ -3192,28 +3757,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" +"checksum aio-limited 0.1.0 (git+https://github.com/paritytech/aio-limited.git)" = "" "checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" "checksum app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d" +"checksum arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0fd1479b7c29641adbd35ff3b5c293922d696a92f25c8c975da3e0acbc87258f" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" +"checksum asn1_der 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f9dec199e4d3e3263a71ec23fd7f0259b3c6963ff83e6bb4871d9d91343d4c81" "checksum assert_matches 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "664470abf00fae0f31c0eb6e1ca12d82961b2a2541ef898bc9dd51a9254d218b" "checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1" "checksum backtrace 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dbdd17cd962b570302f5297aea8648d5923e22e555c2ed2d8b2e34eca646bf6d" "checksum backtrace-sys 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "bff67d0c06556c0b8e6b5f090f0eac52d950d9dfd1d35ba04e4ca3543eaf6a7e" +"checksum base-x 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f59103b47307f76e03bef1633aec7fa9e29bfb5aa6daf5a334f94233c71f6c1" "checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" "checksum base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30e93c03064e7590d0466209155251b90c22e37fab1daf2771582598b5827557" "checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9" +"checksum base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5032d51da2741729bfdaeb2664d9b8c6d9fd1e2b90715c660b6def36628499c2" "checksum base64 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9263aa6a38da271eec5c91a83ce1e800f093c8535788d403d626d8d5c3f8f007" +"checksum bigint 4.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da1dde4308822ffaa13665757273a1b787481212f3f9b1c470a864b179a01f1b" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" +"checksum bs58 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e6ea4851598d7433fbdba71fa2509d9b0df68124b9c0effe7588f5149692d9f" +"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" +"checksum byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96c8b41881888cc08af32d47ac4edd52bc7fa27fef774be47a92443756451304" "checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9" "checksum bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dd32989a66957d3f0cba6588f15d4281a733f4e9ffc43fcd2385f57d3bf99ff" "checksum cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "49ec142f5768efb5b7622aebc3fdbdbb8950a4b9ba996393cb76ef7466e8747d" "checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18" +"checksum chashmap 2.2.1 (git+https://github.com/redox-os/tfs)" = "" "checksum chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cce36c92cb605414e9b824f866f5babe0a0368e39ea07393b9b63cf3844c0e6" +"checksum cid 0.2.3 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" +"checksum circular-buffer 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" "checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "95470235c31c726d72bf2e1f421adc1e65b9d561bf5529612cbe1a72da1467b3" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67" @@ -3228,12 +3807,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crossbeam-utils 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d636a8b3bcc1b409d7ffd3facef8f21dcb4009626adbd0c5e6c4305c07253c7b" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)" = "" +"checksum datastore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" "checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" +"checksum digest 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3cae2388d706b52f2f2f9afe280f9d768be36544bd71d1b8120cb34ea6450b55" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum edit-distance 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3bd26878c3d921f89797a4e1a1711919f999a9f6946bb6f5a4ffda126d297b7e" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" +"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)" = "" "checksum ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a93a43ce2e9f09071449da36bfa7a1b20b950ee344b6904ff23de493b03b386" @@ -3242,11 +3824,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ethcore-io 1.12.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum ethcore-logger 1.12.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum ethcore-network 1.12.0 (git+https://github.com/paritytech/parity.git)" = "" -"checksum ethcore-network-devp2p 1.12.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c48729b8aea8aedb12cf4cb2e5cef439fdfe2dda4a89e47eeebd15778ef53b6" "checksum ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ac59a21a9ce98e188f3dace9eb67a6c4a3c67ec7fbc7218cb827852679dc002" "checksum ethkey 0.3.0 (git+https://github.com/paritytech/parity.git)" = "" +"checksum etrace 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5a3eb49b4ae7e88cc23caa812e8072c9f83a3e202e0b789ff4f9319cf796d8ca" "checksum exit-future 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6c30ec160f83d938faf4dd6fdaba4f42316f1bd3df76b902df2d824f47fa9db7" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa" "checksum fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)" = "" "checksum fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18d6fd718fb4396e7a9c93ac59ba7143501467ca7a143c145b5555a571d5576" @@ -3258,7 +3841,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +"checksum futures-mutex 0.3.0 (git+https://github.com/paritytech/futures-mutex)" = "" "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" +"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" "checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05" "checksum globset 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "142754da2c9b3722affd909f9e27f2a6700a7a303f362971e0a74c652005a43d" "checksum hashdb 0.1.1 (git+https://github.com/paritytech/parity.git)" = "" @@ -3270,7 +3855,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2" "checksum hyper 0.11.27 (registry+https://github.com/rust-lang/crates.io-index)" = "34a590ca09d341e94cddf8e5af0bbccde205d5fbc2fa3c09dd67c7f85cea59d7" "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" -"checksum igd 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a254e265e8810deb357a9de757f784787ec415d056ededf410c0aa460afee9e" +"checksum integer-encoding 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "26746cbc2e680af687e88d717f20ff90079bd10fc984ad57d277cd0e37309fa5" "checksum integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)" = "" "checksum interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "141340095b15ed7491bd3d4ced9d20cebfb826174b6bb03386381f62b01e3d77" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" @@ -3294,6 +3879,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739" "checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" "checksum libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)" = "ac8ebf8343a981e2fa97042b14768f02ed3e1d602eac06cae6166df3c8ced206" +"checksum libp2p 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" +"checksum libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" +"checksum libp2p-dns 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" +"checksum libp2p-floodsub 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" +"checksum libp2p-identify 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" +"checksum libp2p-kad 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" +"checksum libp2p-mplex 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" +"checksum libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" +"checksum libp2p-ping 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" +"checksum libp2p-ratelimit 0.1.1 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" +"checksum libp2p-relay 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" +"checksum libp2p-secio 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" +"checksum libp2p-tcp-transport 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" +"checksum libp2p-transport-timeout 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" +"checksum libp2p-websocket 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" "checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e" "checksum local-encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1ceb20f39ff7ae42f3ff9795f3986b1daad821caaa1e1732a0944103a5a1a66" "checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54" @@ -3309,10 +3909,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum mime 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0b28683d0b09bbc20be1c9b3f6f24854efb1356ffcffee08ea3f6e65596e85fa" "checksum mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "6d771e3ef92d58a8da8df7d6976bfca9371ed1de6619d9d5a5ce5b1f29b85bfe" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" +"checksum multibase 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9c35dac080fd6e16a99924c8dfdef0af89d797dd851adab25feaffacf7850d6" +"checksum multihash 0.8.1-pre (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" +"checksum multistream-select 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" "checksum native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f74dbadc8b43df7864539cedb7bc91345e532fdd913cfdc23ad94f4d2d40fbc0" "checksum net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "9044faf1413a1057267be51b5afba8eb1090bd2231c693664aa1db716fe1eae0" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" +"checksum num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1" "checksum num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac0ea58d64a89d9d6b7688031b3be9358d6c919badcf7fbb0527ccfd891ee45" +"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" "checksum num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775393e285254d2f5004596d69bb8bc1149754570dcc08cf30cabeba67955e28" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" @@ -3326,7 +3932,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac" "checksum parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "901d6514273469bb17380c1ac3f51fb3ce54be1f960e51a6f04901eba313ab8d" "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" -"checksum path 0.1.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum patricia-trie 0.1.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f" @@ -3335,12 +3940,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0" "checksum proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5cb6f960ad471404618e9817c0e5d10b1ae74cfdf01fab89ea0641fe7fb2892" "checksum proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1fa93823f53cfd0f5ac117b189aed6cfdfb2cfc0a9d82e956dd7927595ed7d46" +"checksum protobuf 1.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0100b2cf4cd80bbe249f32146ddb767829da85fdda0ea79c570359620a8933e8" +"checksum protobuf 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a163be69698a5cb7baa28819474344d3a268b3f3e41877e61d5555e3d3add1af" +"checksum protobuf-codegen 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a2af1a097616f8c5602f06e056dd4ce391f3fb276eddc27828a9d26f0df28cff" +"checksum protobuf-codegen-pure 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1db0561391e9b7e20b856a91f269a50ddd3d014f7faeb20c840500c608be82f1" "checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07" "checksum pwasm-utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3a822d2a1624b10c46572c231c149575bcc261c37d84fd3f1a2f5ae1f65515" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" +"checksum rand 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d0d9f869af32e387d9e0f2bdb64326b8ac84c81d5e55459d0bc7526b0fdb3671" +"checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2" "checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8" "checksum rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80e811e76f1dbf68abf87a759083d34600017fc4e10b6bd5ad84a700f9dba4b1" "checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8" @@ -3361,6 +3972,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)" = "" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a" +"checksum rw-stream-sink 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "85fd9df495640643ad2d00443b3d78aae69802ad488debab4f1dd52fc1806ade" "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" @@ -3373,9 +3985,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "79e4620ba6fbe051fc7506fab6f84205823564d55da18d55b695160fb3479cd8" "checksum serde_json 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "93aee34bb692dde91e602871bc792dd319e489c7308cdbbe5f27cf27c64280f5" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" +"checksum sha1 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "171698ce4ec7cbb93babeb3190021b4d72e96ccb98e33d277ae4ea959d6f2d9e" +"checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" "checksum shell32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ee04b46101f57121c9da2b151988283b6beb79b34f5bb29a58ee48cb695122c" "checksum skeptic 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24ebf8a06f5f8bae61ae5bbc7af7aac4ef6907ae975130faba1199e5fe82256a" -"checksum slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6dbdd334bd28d328dad1c41b0ea662517883d8880d8533895ef96c8003dec9c4" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d" "checksum slog 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2f7bfce6405155042d42ec0e645efe43eddedd7be280063ce0623b120014e7f9" @@ -3384,16 +3997,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum slog-scope 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "053344c94c0e2b22da6305efddb698d7c485809427cf40555dc936085f67a9df" "checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013" "checksum smallvec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ee4f357e8cd37bf8822e1b964e96fd39e2cb5a0424f8aaa284ccaccc2162411c" +"checksum smallvec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "872c0ff227000041c520cca51e883b858d388ab0ecf646bab76f065cebaec025" +"checksum smallvec 0.6.0 (git+https://github.com/Vurich/rust-smallvec.git?branch=array-zero)" = "" "checksum smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03dab98ab5ded3a8b43b2c80751194608d0b2aa0f1d46cf95d1c35e192844aa7" "checksum snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)" = "" "checksum snappy-sys 0.1.0 (git+https://github.com/paritytech/rust-snappy)" = "" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" +"checksum stdweb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc7f6353c2ee5407358d063a14cccc1630804527090a6fb5a9489ce4924280fb" "checksum syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6dfd71b2be5a58ee30a6f8ea355ba8290d397131c00dfa55c3d34e6e13db5101" "checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +"checksum tempfile 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11ce2fe9db64b842314052e2421ac61a73ce41b898dc8e3750398b219c5fc1e0" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" @@ -3402,12 +4019,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f" "checksum tokio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d00555353b013e170ed8bc4e13f648a317d1fd12157dbcae13f7013f6cf29f5" "checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" +"checksum tokio-dns-unofficial 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35ca396a652a11b5dd689d96dfd4d7266f9883522bc0f5d99270524b40646aad" "checksum tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8cac2a7883ff3567e9d66bb09100d09b33d90311feca0206c7ca034bc0c55113" "checksum tokio-fs 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76766830bbf9a2d5bfb50c95350d56a2e79e2c80f675967fff448bc615899708" "checksum tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6af9eb326f64b2d6b68438e1953341e00ab3cf54de7e35d92bfc73af8555313a" "checksum tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fbb47ae81353c63c487030659494b295f6cb6576242f907f203473b191b0389" "checksum tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3cedc8e5af5131dc3423ffa4f877cce78ad25259a9a62de0613735a13ebc64b" -"checksum tokio-retry 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f05746ae87dca83a2016b4f5dba5b237b897dd12fd324f60afe282112f16969a" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" "checksum tokio-tcp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec9b094851aadd2caf83ba3ad8e8c4ce65a42104f7b94d9e6550023f0407853f" "checksum tokio-threadpool 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5783254b10c7c84a56f62c74766ef7e5b83d1f13053218c7cab8d3f2c826fa0e" @@ -3423,6 +4040,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum try-lock 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2aa4715743892880f70885373966c83d73ef1b0838a664ef0c76fffd35e7c2" "checksum twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "475352206e7a290c5fccc27624a163e8d0d115f7bb60ca18a64fc9ce056d7435" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" +"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)" = "" "checksum uint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "38051a96565903d81c9a9210ce11076b2218f3b352926baa1f5f6abbdfce8273" @@ -3436,6 +4054,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" "checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum varint 0.1.0 (git+https://github.com/libp2p/rust-libp2p)" = "" +"checksum varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=322769ee562442215518e4fcfdb727a5dd971bc8)" = "" "checksum vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7ed0f6789c8a85ca41bbc1c9d175422116a9869bd1cf31bb08e1493ecce60380" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" @@ -3453,6 +4073,4 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ws 0.7.5 (git+https://github.com/tomusdrw/ws-rs)" = "" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a66b7c2281ebde13cf4391d70d4c7e5946c3c25e72a7b859ca8f677dcd0b0c61" -"checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2" -"checksum xmltree 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9cfb54ca6b8f17d2377219ce485b134d53561b77e1393c7ea416f543a527431" "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" diff --git a/README.md b/README.md index ccf8d7b165937..286d14c9faa48 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,8 @@ polkadot --chain=local --validator --key Alice -d /tmp/alice and in the other, run: ``` -polkadot --chain=local --validator --key Bob -d /tmp/bob --port 30334 --bootnodes 'enode://ALICE_BOOTNODE_ID_HERE@127.0.0.1:30333' +polkadot --chain=local --validator --key Bob -d /tmp/bob --port 30334 + --bootnodes '/ip4/127.0.0.1/tcp/30333/p2p/ALICE_BOOTNODE_ID_HERE' ``` Ensure you replace `ALICE_BOOTNODE_ID_HERE` with the node ID from the output of diff --git a/substrate/network-libp2p/Cargo.toml b/substrate/network-libp2p/Cargo.toml new file mode 100644 index 0000000000000..5a4d404dce8b7 --- /dev/null +++ b/substrate/network-libp2p/Cargo.toml @@ -0,0 +1,30 @@ +[package] +description = "libp2p implementation of the ethcore network library" +homepage = "http://parity.io" +license = "GPL-3.0" +name = "substrate-network-libp2p" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +bytes = "0.4" +fnv = "1.0" +futures = "0.1" +libp2p = { git = "https://github.com/tomaka/libp2p-rs", rev = "322769ee562442215518e4fcfdb727a5dd971bc8", default-features = false, features = ["libp2p-secio"] } +ethcore-network = { git = "https://github.com/paritytech/parity.git" } +ethkey = { git = "https://github.com/paritytech/parity.git" } +parking_lot = "0.5" +log = "0.3" +rand = "0.5.0" +tokio-core = "0.1" +tokio-io = "0.1" +tokio-timer = "0.1" +varint = { git = "https://github.com/libp2p/rust-libp2p" } + +[dev-dependencies] +ethcore-bytes = { git = "https://github.com/paritytech/parity.git" } +ethcore-io = { git = "https://github.com/paritytech/parity.git" } +ethcore-logger = { git = "https://github.com/paritytech/parity.git" } + +[features] +default = [] diff --git a/substrate/network-libp2p/src/custom_proto.rs b/substrate/network-libp2p/src/custom_proto.rs new file mode 100644 index 0000000000000..2b176a7b345da --- /dev/null +++ b/substrate/network-libp2p/src/custom_proto.rs @@ -0,0 +1,270 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see .? + +use bytes::{Bytes, BytesMut}; +use network::ProtocolId; +use libp2p::core::{Multiaddr, ConnectionUpgrade, Endpoint}; +use network::PacketId; +use std::io::Error as IoError; +use std::vec::IntoIter as VecIntoIter; +use futures::{future, Future, stream, Stream, Sink}; +use futures::sync::mpsc; +use tokio_io::{AsyncRead, AsyncWrite}; +use varint::VarintCodec; + +/// Connection upgrade for a single protocol. +/// +/// Note that "a single protocol" here refers to `par` for example. However each protocol can +/// have multiple different versions for networking purposes. +#[derive(Clone)] +pub struct RegisteredProtocol { + // Id of the protocol for API purposes. + id: ProtocolId, + // Base name of the protocol as advertised on the network. + // Ends with `/` so that we can append a version number behind. + base_name: Bytes, + // List of protocol versions that we support, plus their packet count. Ordered in descending + // order so that the best comes first. + // The packet count is used to filter out invalid messages. + supported_versions: Vec<(u8, u8)>, + // Custom data. + custom_data: T, +} + +/// Output of a `RegisteredProtocol` upgrade. +pub struct RegisteredProtocolOutput { + /// Data passed to `RegisteredProtocol::new`. + pub custom_data: T, + + /// Id of the protocol. + pub protocol_id: ProtocolId, + + /// Version of the protocol that was negotiated. + pub protocol_version: u8, + + /// Channel to sender outgoing messages to. Closing this channel closes the connection. + // TODO: consider assembling packet_id here + pub outgoing: mpsc::UnboundedSender, + + /// Stream where incoming messages are received. The stream ends whenever either side is + /// closed. + pub incoming: Box>, +} + +impl RegisteredProtocol { + /// Creates a new `RegisteredProtocol`. The `custom_data` parameter will be passed inside the + /// `RegisteredProtocolOutput`. + pub fn new(custom_data: T, protocol: ProtocolId, versions: &[(u8, u8)]) -> Self { + let mut proto_name = Bytes::from_static(b"/substrate/"); + proto_name.extend_from_slice(&protocol); + proto_name.extend_from_slice(b"/"); + + RegisteredProtocol { + base_name: proto_name, + id: protocol, + supported_versions: { + let mut tmp: Vec<_> = versions.iter().rev().cloned().collect(); + tmp.sort_unstable_by(|a, b| b.1.cmp(&a.1)); + tmp + }, + custom_data: custom_data, + } + } + + /// Returns the ID of the protocol. + pub fn id(&self) -> ProtocolId { + self.id + } + + /// Returns the custom data that was passed to `new`. + pub fn custom_data(&self) -> &T { + &self.custom_data + } +} + +impl ConnectionUpgrade for RegisteredProtocol +where C: AsyncRead + AsyncWrite + 'static, // TODO: 'static :-/ + Maf: Future + 'static, // TODO: 'static :( +{ + type NamesIter = VecIntoIter<(Bytes, Self::UpgradeIdentifier)>; + type UpgradeIdentifier = u8; // Protocol version + + #[inline] + fn protocol_names(&self) -> Self::NamesIter { + // Report each version as an individual protocol. + self.supported_versions.iter().map(|&(ver, _)| { + let num = ver.to_string(); + let mut name = self.base_name.clone(); + name.extend_from_slice(num.as_bytes()); + (name, ver) + }).collect::>().into_iter() + } + + type Output = RegisteredProtocolOutput; + type MultiaddrFuture = Maf; + type Future = future::FutureResult<(Self::Output, Self::MultiaddrFuture), IoError>; + + fn upgrade(self, socket: C, protocol_version: Self::UpgradeIdentifier, _: Endpoint, + remote_addr: Maf) -> Self::Future + { + let packet_count = self.supported_versions + .iter() + .find(|&(v, _)| *v == protocol_version) + .expect("negotiated protocol version that wasn't advertised ; programmer error") + .1; + + // This function is called whenever we successfully negotiated a protocol with a + // remote (both if initiated by us or by the remote) + + // This channel is used to send outgoing packets to the custom_data for this open + // substream. + let (msg_tx, msg_rx) = mpsc::unbounded(); + + // Build the sink for outgoing network bytes, and the stream for incoming instructions. + // `stream` implements `Stream`. + enum Message { + // Received data from the network. + RecvSocket(BytesMut), + // Data to send to the network. + // The packet_id must already be inside the `Bytes`. + SendReq(Bytes), + // The socket has been closed. + Finished, + } + + let (sink, stream) = { + let framed = AsyncRead::framed(socket, VarintCodec::default()); + let msg_rx = msg_rx.map(Message::SendReq) + .chain(stream::once(Ok(Message::Finished))) + .map_err(|()| unreachable!()); + let (sink, stream) = framed.split(); + let stream = stream.map(Message::RecvSocket) + .chain(stream::once(Ok(Message::Finished))); + (sink, msg_rx.select(stream)) + }; + + let incoming = stream::unfold((sink, stream, false), move |(sink, stream, finished)| { + if finished { + return None; + } + + Some(stream + .into_future() + .map_err(|(err, _)| err) + .and_then(move |(message, stream)| { + match message { + Some(Message::RecvSocket(mut data)) => { + // The `data` should be prefixed by the packet ID, therefore an + // empty packet is invalid. + if data.is_empty() { + debug!(target: "sub-libp2p", "ignoring incoming packet \ + because it was empty"); + let f = future::ok((None, (sink, stream, false))); + return future::Either::A(f); + } + + let packet_id = data[0]; + let data = data.split_off(1); + + if packet_id >= packet_count { + debug!(target: "sub-libp2p", "ignoring incoming packet \ + because packet_id {} is too large", packet_id); + let f = future::ok((None, (sink, stream, false))); + future::Either::A(f) + } else { + let out = Some((packet_id, data.freeze())); + let f = future::ok((out, (sink, stream, false))); + future::Either::A(f) + } + }, + + Some(Message::SendReq(data)) => { + let fut = sink.send(data) + .map(move |sink| (None, (sink, stream, false))); + future::Either::B(fut) + }, + + Some(Message::Finished) | None => { + let f = future::ok((None, (sink, stream, true))); + future::Either::A(f) + }, + } + })) + }).filter_map(|v| v); + + let out = RegisteredProtocolOutput { + custom_data: self.custom_data, + protocol_id: self.id, + protocol_version: protocol_version, + outgoing: msg_tx, + incoming: Box::new(incoming), + }; + + future::ok((out, remote_addr)) + } +} + +// Connection upgrade for all the protocols contained in it. +#[derive(Clone)] +pub struct RegisteredProtocols(pub Vec>); + +impl RegisteredProtocols { + /// Finds a protocol in the list by its id. + pub fn find_protocol(&self, protocol: ProtocolId) -> Option<&RegisteredProtocol> { + self.0.iter().find(|p| p.id == protocol) + } + + /// Returns true if the given protocol is in the list. + pub fn has_protocol(&self, protocol: ProtocolId) -> bool { + self.0.iter().any(|p| p.id == protocol) + } +} + +impl Default for RegisteredProtocols { + fn default() -> Self { + RegisteredProtocols(Vec::new()) + } +} + +impl ConnectionUpgrade for RegisteredProtocols +where C: AsyncRead + AsyncWrite + 'static, // TODO: 'static :-/ + Maf: Future + 'static, // TODO: 'static :( +{ + type NamesIter = VecIntoIter<(Bytes, Self::UpgradeIdentifier)>; + type UpgradeIdentifier = (usize, as ConnectionUpgrade>::UpgradeIdentifier); + + fn protocol_names(&self) -> Self::NamesIter { + // We concat the lists of `RegisteredProtocol::protocol_names` for each protocol. + self.0.iter().enumerate().flat_map(|(n, proto)| { + ConnectionUpgrade::::protocol_names(proto) + .map(move |(name, id)| (name, (n, id))) + }).collect::>().into_iter() + } + + type Output = as ConnectionUpgrade>::Output; + type MultiaddrFuture = as ConnectionUpgrade>::MultiaddrFuture; + type Future = as ConnectionUpgrade>::Future; + + #[inline] + fn upgrade(self, socket: C, (protocol_index, inner_proto_id): Self::UpgradeIdentifier, + endpoint: Endpoint, remote_addr: Maf) -> Self::Future + { + self.0.into_iter() + .nth(protocol_index) + .expect("invalid protocol index ; programmer logic error") + .upgrade(socket, inner_proto_id, endpoint, remote_addr) + } +} diff --git a/substrate/network-libp2p/src/lib.rs b/substrate/network-libp2p/src/lib.rs new file mode 100644 index 0000000000000..f6866bec21e9e --- /dev/null +++ b/substrate/network-libp2p/src/lib.rs @@ -0,0 +1,49 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see .? + +#![type_length_limit = "67108864"] + +extern crate parking_lot; +extern crate fnv; +extern crate futures; +extern crate tokio_core; +extern crate tokio_io; +extern crate tokio_timer; +extern crate ethkey; +extern crate ethcore_network as network; +extern crate libp2p; +extern crate rand; +extern crate bytes; +extern crate varint; + +#[macro_use] +extern crate log; + +mod custom_proto; +mod network_state; +mod service; +mod timeouts; +mod transport; + +pub use service::NetworkService; + +/// Check if node url is valid +pub fn validate_node_url(url: &str) -> Result<(), network::Error> { + match url.parse::() { + Ok(_) => Ok(()), + Err(_) => Err(network::ErrorKind::InvalidNodeId.into()), + } +} diff --git a/substrate/network-libp2p/src/network_state.rs b/substrate/network-libp2p/src/network_state.rs new file mode 100644 index 0000000000000..57bc5e03e01ea --- /dev/null +++ b/substrate/network-libp2p/src/network_state.rs @@ -0,0 +1,526 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see .? + +use bytes::Bytes; +use fnv::{FnvHashMap, FnvHashSet}; +use futures::sync::mpsc; +use libp2p::core::{Multiaddr, AddrComponent, Endpoint, PeerId as PeerstorePeerId}; +use libp2p::peerstore::{Peerstore, PeerAccess}; +use libp2p::peerstore::json_peerstore::JsonPeerstore; +use libp2p::peerstore::memory_peerstore::MemoryPeerstore; +use network::{Error, ErrorKind, NetworkConfiguration, NonReservedPeerMode}; +use network::{PeerId, ProtocolId, SessionInfo}; +use parking_lot::{Mutex, RwLock}; +use std::cmp; +use std::io::{Error as IoError, ErrorKind as IoErrorKind}; +use std::path::Path; +use std::sync::atomic; +use std::time::Duration; + +// File where the peers are stored. +const NODES_FILE: &str = "nodes.json"; + +// Common struct shared throughout all the components of the service. +pub struct NetworkState { + // Contains the information about the network. + peerstore: PeersStorage, + + // Active connections. + connections: RwLock, + + // `min_peers` taken from the configuration. + min_peers: u32, + // `max_peers` taken from the configuration. + max_peers: u32, + + // If true, only reserved peers can connect. + reserved_only: atomic::AtomicBool, + // List of the IDs of the reserved peers. + reserved_peers: RwLock>, + + // Each peer gets assigned a new unique ID. This ID increases linearly. + next_peer_id: atomic::AtomicUsize, + + // List of the IDs of the disabled peers. These peers will see their connections refused. + disabled_peers: RwLock>, +} + +enum PeersStorage { + // Peers are stored in memory. Nothing is stored on disk. + Memory(MemoryPeerstore), + // Peers are stored in a JSON file on the disk. + Json(JsonPeerstore), +} + +struct Connections { + // For each libp2p peer ID, the ID of the peer in the API we expose. + // Also corresponds to the index in `info_by_peer`. + peer_by_nodeid: FnvHashMap, + + // For each peer ID, information about our connection to this peer. + info_by_peer: FnvHashMap, +} + +struct PeerConnectionInfo { + // A list of message senders per protocol, and the protocol version. + // The sender can be used to transmit data for the remote. Note that the packet_id has to be + // inside the `Bytes`. + // Closing the sender will drop the substream of this protocol. + senders: Vec<(ProtocolId, mpsc::UnboundedSender, u8)>, + + // Id of the peer. + id: PeerstorePeerId, + + // True if this connection was initiated by us. + // Note that it is theoretically possible that we dial the remote at the same time they dial + // us, in which case the protocols may be dispatched between both connections, and in which + // case the value here will be racy. + originated: bool, + + // Latest known ping duration. + ping: Mutex>, + + // The client version of the remote, or `None` if not known. + client_version: Option, + + // The multiaddress of the remote, or `None` if not known. + remote_address: Option, + + // The local multiaddress used to communicate with the remote, or `None` if not known. + local_address: Option, +} + +impl NetworkState { + pub fn new(config: &NetworkConfiguration) -> Result { + // Build the storage for peers, including the bootstrap nodes. + let peerstore = if let Some(ref path) = config.net_config_path { + let path = Path::new(path).join(NODES_FILE); + if let Ok(peerstore) = JsonPeerstore::new(path.clone()) { + debug!(target: "sub-libp2p", "Initialized peer store for JSON file {:?}", path); + PeersStorage::Json(peerstore) + } else { + warn!(target: "sub-libp2p", "Failed to open peer storage {:?} ; peers won't \ + be saved", path); + PeersStorage::Memory(MemoryPeerstore::empty()) + } + } else { + debug!(target: "sub-libp2p", "No peers file configured ; peers won't be saved"); + PeersStorage::Memory(MemoryPeerstore::empty()) + }; + + for bootnode in config.boot_nodes.iter() { + parse_and_add_to_peerstore(bootnode, &peerstore)?; + } + + let reserved_peers = { + let mut reserved_peers = FnvHashSet::with_capacity_and_hasher(config.reserved_nodes.len(), Default::default()); + for peer in config.reserved_nodes.iter() { + let id = parse_and_add_to_peerstore(peer, &peerstore)?; + reserved_peers.insert(id); + } + RwLock::new(reserved_peers) + }; + + let expected_max_peers = cmp::max(config.max_peers as usize, config.reserved_nodes.len()); + + Ok(NetworkState { + peerstore, + min_peers: config.min_peers, + max_peers: config.max_peers, + connections: RwLock::new(Connections { + peer_by_nodeid: FnvHashMap::with_capacity_and_hasher(expected_max_peers, Default::default()), + info_by_peer: FnvHashMap::with_capacity_and_hasher(expected_max_peers, Default::default()), + }), + reserved_only: atomic::AtomicBool::new(false), + reserved_peers, + next_peer_id: atomic::AtomicUsize::new(0), + disabled_peers: RwLock::new(Default::default()), + }) + } + + /// Returns all the IDs of the peer we have knowledge of. + /// + /// This includes peers we are not connected to. + pub fn known_peers(&self) -> impl Iterator { + match self.peerstore { + PeersStorage::Memory(ref mem) => mem.peers().collect::>().into_iter(), + PeersStorage::Json(ref json) => json.peers().collect::>().into_iter(), + } + } + + /// Returns true if we are connected to any peer at all. + pub fn has_connected_peer(&self) -> bool { + !self.connections.read().peer_by_nodeid.is_empty() + } + + /// Get a list of all connected peers by id. + pub fn connected_peers(&self) -> Vec { + self.connections.read().peer_by_nodeid.values().cloned().collect() + } + + /// Returns true if the given `PeerId` is valid. + /// + /// `PeerId`s are never reused, so once this function returns `false` it will never return + /// `true` again for the same `PeerId`. + pub fn is_peer_connected(&self, peer: PeerId) -> bool { + self.connections.read().info_by_peer.contains_key(&peer) + } + + /// Reports the ping of the peer. Returned later by `session_info()`. + /// No-op if the `peer_id` is not valid/expired. + pub fn report_ping(&self, peer_id: PeerId, ping: Duration) { + let connections = self.connections.read(); + let info = match connections.info_by_peer.get(&peer_id) { + Some(info) => info, + None => return, + }; + + *info.ping.lock() = Some(ping); + } + + /// If we're connected to a peer with the given protocol, returns information about the + /// connection. Otherwise, returns `None`. + pub fn session_info(&self, peer: PeerId, protocol: ProtocolId) -> Option { + let connections = self.connections.read(); + let info = match connections.info_by_peer.get(&peer) { + Some(info) => info, + None => return None, + }; + + let protocol_version = match info.senders.iter().find(|&(ref p, _, _)| p == &protocol) { + Some(&(_, _, version)) => version as u32, + None => return None, + }; + + /*let node_id = self.peer_by_nodeid.read().iter() + .find(|&(_, &p)| p == peer) + .map(|n| n.clone());*/ + + let ping = info.ping.lock().clone(); + + Some(SessionInfo { + id: None, // TODO: ???? what to do??? wrong format! + client_version: info.client_version.clone().take().unwrap_or(String::new()), + protocol_version, + capabilities: Vec::new(), // TODO: list of supported protocols ; hard + peer_capabilities: Vec::new(), // TODO: difference with `peer_capabilities`? + ping, + originated: info.originated, + remote_address: info.remote_address.as_ref().map(|a| a.to_string()).unwrap_or(String::new()), + local_address: info.local_address.as_ref().map(|a| a.to_string()).unwrap_or(String::new()), + }) + } + + /// If we're connected to a peer with the given protocol, returns the protocol version. + /// Otherwise, returns `None`. + pub fn protocol_version(&self, peer: PeerId, protocol: ProtocolId) -> Option { + let connections = self.connections.read(); + let peer = match connections.info_by_peer.get(&peer) { + Some(peer) => peer, + None => return None, + }; + + peer.senders.iter().find(|p| p.0 == protocol).map(|p| p.2) + } + + /// Equivalent to `session_info(peer).map(|info| info.client_version)`. + pub fn peer_client_version(&self, peer: PeerId, protocol: ProtocolId) -> Option { + // TODO: implement more directly, without going through `session_info` + self.session_info(peer, protocol) + .map(|info| info.client_version) + } + + /// Adds an address discovered by Kademlia. + /// Note that we don't have to be connected to a peer to add an address to it. + pub fn add_kad_discovered_addr(&self, node_id: &PeerstorePeerId, addr: Multiaddr) { + match self.peerstore { + PeersStorage::Memory(ref mem) => { + mem.peer_or_create(node_id) + .add_addr(addr, Duration::from_secs(3600)) + } + PeersStorage::Json(ref json) => { + json.peer_or_create(node_id) + .add_addr(addr, Duration::from_secs(3600)) + } + } + } + + /// Returns the known multiaddresses of a peer. + pub fn addrs_of_peer(&self, node_id: &PeerstorePeerId) -> Vec { + match self.peerstore { + PeersStorage::Memory(ref mem) => { + mem + .peer(node_id) + .into_iter() + .flat_map(|p| p.addrs()) + .collect::>() + } + PeersStorage::Json(ref json) => { + json + .peer(node_id) + .into_iter() + .flat_map(|p| p.addrs()) + .collect::>() + } + } + } + + /// Adds a reserved peer to the list of reserved peers. + /// Returns an error if the peer address is invalid. + pub fn add_reserved_peer(&self, peer: &str) -> Result<(), Error> { + let id = parse_and_add_to_peerstore(peer, &self.peerstore)?; + self.reserved_peers.write().insert(id); + Ok(()) + } + + /// Removes the peer from the list of reserved peers. If we're in reserved mode, drops any + /// active connection to this peer. + /// Returns an error if the peer address is invalid. + pub fn remove_reserved_peer(&self, peer: &str) -> Result<(), Error> { + let id = parse_and_add_to_peerstore(peer, &self.peerstore)?; + self.reserved_peers.write().remove(&id); + + // Dropping the peer if we're in reserved mode. + if self.reserved_only.load(atomic::Ordering::SeqCst) { + let mut connections = self.connections.write(); + if let Some(peer_id) = connections.peer_by_nodeid.remove(&id) { + connections.info_by_peer.remove(&peer_id); + } + } + + Ok(()) + } + + /// Set the non-reserved peer mode. + pub fn set_non_reserved_mode(&self, mode: NonReservedPeerMode) { + match mode { + NonReservedPeerMode::Accept => { + self.reserved_only.store(false, atomic::Ordering::SeqCst); + }, + NonReservedPeerMode::Deny => { + self.reserved_only.store(true, atomic::Ordering::SeqCst); + // TODO: drop existing peers? + }, + } + } + + /// Returns true if reserved mode is enabled. + pub fn is_reserved_only(&self) -> bool { + self.reserved_only.load(atomic::Ordering::Relaxed) + } + + /// Returns true if we should open a new outgoing connection to a peer. + /// This takes into account the number of active peers. + pub fn should_open_outgoing_connecs(&self) -> bool { + !self.reserved_only.load(atomic::Ordering::Relaxed) && + self.connections.read().peer_by_nodeid.len() < self.min_peers as usize + } + + /// Returns true if we are connected to the given node. + pub fn has_connection(&self, node_id: &PeerstorePeerId) -> bool { + let connections = self.connections.read(); + connections.peer_by_nodeid.contains_key(node_id) + } + + /// Try to add a new connection to a node in the list. + /// + /// Returns a `PeerId` to allow further interfacing with this connection. Note that all + /// `PeerId`s are unique and never reused. + /// + /// Can return an error if we are refusing the connection to the remote. + /// + /// You must pass an `UnboundedSender` which will be used by the `send` method. Actually + /// sending the data is not covered by this code. + /// + /// The various methods of the `NetworkState` that close a connection do so by dropping this + /// sender. + pub fn accept_connection(&self, node_id: PeerstorePeerId, protocol_id: ProtocolId, protocol_version: u8, endpoint: Endpoint, msg_tx: mpsc::UnboundedSender) -> Result { + if self.disabled_peers.read().contains(&node_id) { + debug!(target: "sub-libp2p", "Refusing node {:?} because it was disabled", node_id); + return Err(IoError::new(IoErrorKind::PermissionDenied, "disabled peer")); + } + + let node_is_reserved = self.reserved_peers.read().contains(&node_id); + + let mut connections = self.connections.write(); + let connections = &mut *connections; + let peer_by_nodeid = &mut connections.peer_by_nodeid; + let info_by_peer = &mut connections.info_by_peer; + + if !node_is_reserved { + if self.reserved_only.load(atomic::Ordering::Relaxed) || + peer_by_nodeid.len() >= self.max_peers as usize + { + debug!(target: "sub-libp2p", "Refusing node {:?} because we reached the max \ + number of peers", node_id); + return Err(IoError::new(IoErrorKind::PermissionDenied, "maximum number of peers reached")); + } + } + + let peer_id = *peer_by_nodeid.entry(node_id.clone()).or_insert_with(|| { + let new_id = self.next_peer_id.fetch_add(1, atomic::Ordering::Relaxed); + info_by_peer.insert(new_id, PeerConnectionInfo { + senders: Vec::new(), // TODO: Vec::with_capacity(num_registered_protocols), + id: node_id.clone(), + originated: endpoint == Endpoint::Dialer, + ping: Mutex::new(None), + client_version: None, + local_address: None, + remote_address: None, + }); + new_id + }); + + let senders = &mut info_by_peer.get_mut(&peer_id).expect("network state inconsistency").senders; + if !senders.iter().any(|&(prot, _, _)| prot == protocol_id) { + senders.push((protocol_id.clone(), msg_tx, protocol_version)); + } + + Ok(peer_id) + } + + /// Sends some data to the given peer, using the sender that was passed to `accept_connection`. + pub fn send(&self, protocol: ProtocolId, peer_id: PeerId, message: Bytes) -> Result<(), Error> { + if let Some(peer) = self.connections.read().info_by_peer.get(&peer_id) { + if let Some(sender) = peer.senders.iter().find(|elem| elem.0 == protocol).map(|e| &e.1) { + sender.unbounded_send(message) + .map_err(|err| { + ErrorKind::Io(IoError::new(IoErrorKind::Other, err)) + })?; + Ok(()) + + } else { + // We are connected to this peer, but not with the current protocol. + debug!(target: "sub-libp2p", "Tried to send message to peer {} for which we aren't \ + connected with the requested protocol", peer_id); + return Err(ErrorKind::PeerNotFound.into()); + } + } else { + debug!(target: "sub-libp2p", "Tried to send message to invalid peer ID {}", peer_id); + return Err(ErrorKind::PeerNotFound.into()); + } + } + + /// Disconnects a peer, if a connection exists (ie. drops the sender that was passed to + /// `accept_connection`). + pub fn disconnect_peer(&self, peer_id: PeerId) { + let mut connections = self.connections.write(); + if let Some(peer_info) = connections.info_by_peer.remove(&peer_id) { + let old = connections.peer_by_nodeid.remove(&peer_info.id); + debug_assert_eq!(old, Some(peer_id)); + } + } + + /// Disconnects all the peers. + /// This destroys all the senders that were passed to `accept_connection`. + pub fn disconnect_all(&self) { + let mut connec = self.connections.write(); + *connec = Connections { + info_by_peer: FnvHashMap::with_capacity_and_hasher(connec.peer_by_nodeid.capacity(), Default::default()), + peer_by_nodeid: FnvHashMap::with_capacity_and_hasher(connec.peer_by_nodeid.capacity(), Default::default()), + }; + } + + /// Disables a peer. This adds the peer to the list of disabled peers, and drops any existing + /// connections if necessary (ie. drops the sender that was passed to `accept_connection`). + pub fn disable_peer(&self, peer_id: PeerId) { + // TODO: what do we do if the peer is reserved? + let mut connections = self.connections.write(); + let peer_info = if let Some(peer_info) = connections.info_by_peer.remove(&peer_id) { + let old = connections.peer_by_nodeid.remove(&peer_info.id); + debug_assert_eq!(old, Some(peer_id)); + peer_info + } else { + return; + }; + + drop(connections); + self.disabled_peers.write().insert(peer_info.id.clone()); + } + + /// Returns true if a peer is disabled. + pub fn is_peer_disabled(&self, node_id: &PeerstorePeerId) -> bool { + self.disabled_peers.read().contains(&node_id) + } +} + +impl Drop for NetworkState { + fn drop(&mut self) { + match self.peerstore { + PeersStorage::Memory(_) => (), + PeersStorage::Json(ref json) => { + match json.flush() { + Ok(()) => { + debug!(target: "sub-libp2p", "Flushed JSON peer store to disk"); + } + Err(err) => { + warn!(target: "sub-libp2p", "Failed to flush changes to JSON \ + peer store: {}", err); + } + } + } + } + } +} + +// Parses an address of the form `/ip4/x.x.x.x/tcp/x/p2p/xxxxxx`, and adds it to the given +// peerstore. Returns the corresponding peer ID. +fn parse_and_add_to_peerstore(addr_str: &str, peerstore: &PeersStorage) + -> Result +{ + let mut addr: Multiaddr = addr_str.parse().map_err(|_| ErrorKind::AddressParse)?; + let p2p_component = addr.pop().ok_or(ErrorKind::AddressParse)?; + let peer_id = match p2p_component { + AddrComponent::P2P(key) | AddrComponent::IPFS(key) => { + PeerstorePeerId::from_bytes(key).map_err(|_| ErrorKind::AddressParse)? + } + _ => return Err(ErrorKind::BadProtocol.into()), + }; + + // Registering the bootstrap node with a TTL of 100000 years TODO: wrong + match peerstore { + PeersStorage::Memory(ref peerstore) => { + peerstore + .peer_or_create(&peer_id) + .add_addr(addr, Duration::from_secs(100000 * 365 * 24 * 3600)); + } + PeersStorage::Json(ref peerstore) => { + peerstore + .peer_or_create(&peer_id) + .add_addr(addr, Duration::from_secs(100000 * 365 * 24 * 3600)); + } + } + + Ok(peer_id) +} + +#[cfg(test)] +mod tests { + use futures::sync::mpsc; + use libp2p::core::{Endpoint, PublicKey}; + use network_state::NetworkState; + + #[test] + fn refuse_disabled_peer() { + let state = NetworkState::new(&Default::default()).unwrap(); + let example_peer = PublicKey::Rsa(vec![1, 2, 3, 4]).into_peer_id(); + + let peer_id = state.accept_connection(example_peer.clone(), [1, 2, 3], 1, Endpoint::Dialer, mpsc::unbounded().0).unwrap(); + state.disable_peer(peer_id); + + assert!(state.accept_connection(example_peer.clone(), [1, 2, 3], 1, Endpoint::Dialer, mpsc::unbounded().0).is_err()); + } +} diff --git a/substrate/network-libp2p/src/service.rs b/substrate/network-libp2p/src/service.rs new file mode 100644 index 0000000000000..e0e3595255d69 --- /dev/null +++ b/substrate/network-libp2p/src/service.rs @@ -0,0 +1,832 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see .? + +use bytes::Bytes; +use network::{Error, ErrorKind, NetworkConfiguration, NetworkProtocolHandler, NonReservedPeerMode}; +use network::{NetworkContext, PeerId, ProtocolId}; +use parking_lot::{Mutex, RwLock}; +use libp2p; +use libp2p::multiaddr::{AddrComponent, Multiaddr}; +use libp2p::kad::{KademliaConfig, KademliaControllerPrototype, KademliaUpgrade, KademliaPeerReqStream, Peer, ConnectionType, QueryEvent}; +use libp2p::identify::{IdentifyInfo, IdentifyOutput, IdentifyTransportOutcome, IdentifyProtocolConfig, PeerIdTransport}; +use libp2p::core::{upgrade, Transport, MuxedTransport, ConnectionUpgrade, Endpoint, PeerId as PeerstorePeerId, PublicKey, SwarmController}; +use libp2p::{ping, secio}; +use network::{PacketId, SessionInfo, ConnectionFilter, TimerToken}; +use rand; +use std::io::{Error as IoError, ErrorKind as IoErrorKind}; +use std::iter; +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +use std::sync::Arc; +use std::sync::mpsc as sync_mpsc; +use std::thread; +use std::time::{Duration, Instant}; +use futures::{future, Future, Stream}; +use futures::sync::{mpsc, oneshot}; +use tokio_core::reactor::{Core, Handle}; +use tokio_io::{AsyncRead, AsyncWrite}; +use tokio_timer; + +use custom_proto::{RegisteredProtocol, RegisteredProtocols, RegisteredProtocolOutput}; +use network_state::NetworkState; +use timeouts; +use transport; + +/// IO Service with networking. +pub struct NetworkService { + shared: Arc, + + // Holds the networking-running background thread alive. The `Option` is `None` if the service + // is stopped. + // Sending a message on the channel will trigger the end of the background thread. We can + // then wait on the join handle. + bg_thread: Mutex, thread::JoinHandle<()>)>>, +} + +// Common struct shared throughout all the components of the service. +struct Shared { + // Original configuration of the service. + config: NetworkConfiguration, + + // Contains the state of the network. + network_state: NetworkState, + + // List of protocols available on the network. It is a logic error to remote protocols from + // this list, and the code may assume that protocols stay at the same index forever. + protocols: RwLock>>, + + // Use this channel to send a timeout request to the background thread's events loop. + // After the timeout, elapsed, it will call `timeout` on the `NetworkProtocolHandler`. + // This can be closed if the background thread is not running. The sender will be overwritten + // every time we start the service. + timeouts_register_tx: RwLock, ProtocolId, TimerToken))>>, + + // Contains the addresses we known about ourselves. + listened_addrs: RwLock>, +} + +impl NetworkService { + /// Starts IO event loop + pub fn new(config: NetworkConfiguration, filter: Option>) -> Result { + // TODO: for now `filter` is always `None` ; remove it from the code or implement it + assert!(filter.is_none()); + + let listened_addrs = RwLock::new(vec![ + config_to_listen_addr(&config) + ]); + + let shared = Arc::new(Shared { + network_state: NetworkState::new(&config)?, + protocols: RwLock::new(Default::default()), + config, + timeouts_register_tx: RwLock::new(mpsc::unbounded().0), + listened_addrs, + }); + + Ok(NetworkService { + shared, + bg_thread: Mutex::new(None), + }) + } + + /// Register a new protocol handler with the event loop. + pub fn register_protocol(&self, handler: Arc, protocol: ProtocolId, versions: &[(u8, u8)]) { + if self.shared.network_state.has_connected_peer() { + // TODO: figure out if that's correct + warn!(target: "sub-libp2p", "a new network protocol was registered while the service \ + was already active ; this is a programmer error"); + } + + self.shared.protocols.write().0 + .push(RegisteredProtocol::new(handler.clone(), protocol, versions)); + + handler.initialize(&NetworkContextImpl { + inner: self.shared.clone(), + protocol: protocol.clone(), + current_peer: None, + }); + } + + /// Returns network configuration. + pub fn config(&self) -> &NetworkConfiguration { + &self.shared.config + } + + pub fn external_url(&self) -> Option { + // TODO: in the context of libp2p, it is hard to define what an external URL is, as + // different nodes can have multiple different ways to reach us + None + } + + /// Start network IO + // TODO (design): the notion of having a `NetworkService` alive should mean that it is + // running ; the `start` and `stop` functions are bad design + pub fn start(&self) -> Result<(), (Error, Option)> { + // TODO: check that service is started already? + + *self.shared.protocols.write() = Default::default(); + + // channel we use to signal success or failure of the bg thread initialization process + let (init_tx, init_rx) = sync_mpsc::channel(); + // channel the main thread uses to signal the bg thread that it should stop + let (close_tx, close_rx) = oneshot::channel(); + let (timeouts_register_tx, timeouts_register_rx) = mpsc::unbounded(); + let shared = self.shared.clone(); + let join_handle = thread::spawn(move || { + // Tokio core that is going to run everything in this thread. + let mut core = match Core::new() { + Ok(c) => c, + Err(err) => { let _ = init_tx.send(Err(err.into())); return; } + }; + + let fut = match init_thread(core.handle(), shared, timeouts_register_rx, close_rx) { + Ok(future) => { + debug!(target: "sub-libp2p", "Successfully started networking service"); + let _ = init_tx.send(Ok(())); + future + }, + Err(err) => { + let _ = init_tx.send(Err(err)); + return; + } + }; + + match core.run(fut) { + Ok(()) => { + debug!(target: "sub-libp2p", "libp2p future finished") + }, + Err(err) => { + error!(target: "sub-libp2p", "error while running libp2p: {:?}", err) + }, + } + }); + + init_rx.recv().expect("libp2p background thread panicked") + .map_err(|err| (err, self.shared.config.listen_address.clone()))?; + + *self.bg_thread.lock() = Some((close_tx, join_handle)); + *self.shared.timeouts_register_tx.write() = timeouts_register_tx; + Ok(()) + } + + /// Stop network IO. + pub fn stop(&self) { + if let Some((close_tx, join)) = self.bg_thread.lock().take() { + let _ = close_tx.send(()); + if let Err(e) = join.join() { + warn!(target: "sub-libp2p", "error while waiting on libp2p background \ + thread: {:?}", e); + } + } + + debug_assert!(!self.shared.network_state.has_connected_peer()); + } + + /// Get a list of all connected peers by id. + pub fn connected_peers(&self) -> Vec { + self.shared.network_state.connected_peers() + } + + /// Try to add a reserved peer. + pub fn add_reserved_peer(&self, peer: &str) -> Result<(), Error> { + // TODO: try to dial the peer? + self.shared.network_state.add_reserved_peer(peer) + } + + /// Try to remove a reserved peer. + pub fn remove_reserved_peer(&self, peer: &str) -> Result<(), Error> { + self.shared.network_state.remove_reserved_peer(peer) + } + + /// Set the non-reserved peer mode. + pub fn set_non_reserved_mode(&self, mode: NonReservedPeerMode) { + self.shared.network_state.set_non_reserved_mode(mode) + } + + /// Executes action in the network context + pub fn with_context(&self, protocol: ProtocolId, action: F) where F: FnOnce(&NetworkContext) { + self.with_context_eval(protocol, action); + } + + /// Evaluates function in the network context + pub fn with_context_eval(&self, protocol: ProtocolId, action: F) -> Option + where F: FnOnce(&NetworkContext) -> T + { + if !self.shared.protocols.read().has_protocol(protocol) { + return None; + } + + Some(action(&NetworkContextImpl { + inner: self.shared.clone(), + protocol: protocol.clone(), + current_peer: None, + })) + } +} + +impl Drop for NetworkService { + fn drop(&mut self) { + self.stop(); + } +} + +#[derive(Clone)] +struct NetworkContextImpl { + inner: Arc, + protocol: ProtocolId, + current_peer: Option, +} + +impl NetworkContext for NetworkContextImpl { + fn send(&self, peer: PeerId, packet_id: PacketId, data: Vec) -> Result<(), Error> { + self.send_protocol(self.protocol, peer, packet_id, data) + } + + fn send_protocol(&self, protocol: ProtocolId, peer: PeerId, packet_id: PacketId, data: Vec) -> Result<(), Error> { + trace!(target: "sub-libp2p", "Sending message of len {} to peer {}", data.len(), peer); + debug_assert!(self.inner.protocols.read().has_protocol(protocol), + "invalid protocol id requested in the API of the libp2p networking"); + // TODO: restore + //debug_assert!(packet_id < self.inner.protocols.read().iter().find(|p| p.id == protocol).unwrap().packet_count, + // "invalid packet id requested in the API of the libp2p networking"); + // TODO: could be "optimized" by building `message` only after checking the validity of + // the peer, but that's probably not worth the effort + let mut message = Bytes::with_capacity(1 + data.len()); + message.extend_from_slice(&[packet_id]); + message.extend_from_slice(&data); + self.inner.network_state.send(protocol, peer, message) + } + + fn respond(&self, packet_id: PacketId, data: Vec) -> Result<(), Error> { + if let Some(peer) = self.current_peer { + self.send_protocol(self.protocol, peer, packet_id, data) + } else { + panic!("respond() called outside of a received message"); + } + } + + fn disable_peer(&self, peer: PeerId) { + debug!(target: "sub-libp2p", "Request to disable peer {}", peer); + self.inner.network_state.disable_peer(peer); + } + + fn disconnect_peer(&self, peer: PeerId) { + debug!(target: "sub-libp2p", "Request to disconnect peer {}", peer); + self.inner.network_state.disconnect_peer(peer); + } + + fn is_expired(&self) -> bool { + if let Some(current_peer) = self.current_peer { + !self.inner.network_state.is_peer_connected(current_peer) + } else { + // TODO: is this correct? + true + } + } + + fn register_timer(&self, token: usize, duration: Duration) -> Result<(), Error> { + let handler = self.inner.protocols + .read() + .find_protocol(self.protocol) + .ok_or(ErrorKind::BadProtocol)? + .custom_data() + .clone(); + let at = Instant::now() + duration; + self.inner.timeouts_register_tx.read() + .unbounded_send((at, (handler, self.protocol, token))) + .map_err(|err| { + ErrorKind::Io(IoError::new(IoErrorKind::Other, err)) + })?; + Ok(()) + } + + fn peer_client_version(&self, peer: PeerId) -> String { + // Devp2p returns "unknown" on unknown peer ID, so we do the same. + self.inner.network_state.peer_client_version(peer, self.protocol) + .unwrap_or_else(|| "unknown".to_string()) + } + + fn session_info(&self, peer: PeerId) -> Option { + self.inner.network_state.session_info(peer, self.protocol) + } + + fn protocol_version(&self, protocol: ProtocolId, peer: PeerId) -> Option { + self.inner.network_state.protocol_version(peer, protocol) + } + + fn subprotocol_name(&self) -> ProtocolId { + self.protocol.clone() + } +} + +// Builds the main `Future` for the network service. +// +// - `timeouts_register_rx` should receive newly-registered timeouts. +// - `close_rx` should be triggered when we want to close the network. +fn init_thread(core: Handle, shared: Arc, + timeouts_register_rx: mpsc::UnboundedReceiver<(Instant, (Arc, ProtocolId, TimerToken))>, + close_rx: oneshot::Receiver<()>) -> Result, Error> +{ + // TODO: use key from the config ; however that requires supporting secp256k1 in libp2p + // see https://github.com/libp2p/rust-libp2p/issues/228 + let local_private_key = secio::SecioKeyPair::ed25519_generated().unwrap(); + let local_public_key = local_private_key.to_public_key(); + let local_peer_id = local_public_key.clone().into_peer_id(); + info!(target: "sub-libp2p", "Local node id = {:?}", local_peer_id); // TODO: debug! instead? + + // Configuration for Kademlia DHT. + let kad_config = KademliaControllerPrototype::new(KademliaConfig { + parallelism: 3, + local_peer_id: local_peer_id.clone(), + timeout: Duration::from_secs(10), + }, shared.network_state.known_peers()); + let kad_upgrade = KademliaUpgrade::from_prototype(&kad_config); + + // Build the transport layer. + let transport = { + let base = transport::build_transport(core.clone()); + + let addr_resolver = { + let shared = shared.clone(); + move |peer_id| { + let addrs = shared.network_state.addrs_of_peer(&peer_id); + trace!(target: "sub-libp2p", "Peer store: loaded {} addresses for {:?}", + addrs.len(), peer_id); + addrs.into_iter() + } + }; + + PeerIdTransport::new(base.clone(), addr_resolver) + .and_then({ + let shared = shared.clone(); + move |out, _, remote_addr| { + let info = out.info.map(move |info| { + let peer_id = info.info.public_key.clone().into_peer_id(); + // TODO: this is expensive, but eventually the multiaddr will be directly + // part of the configuration, so we don't really care + let original_listened_addr = config_to_listen_addr(&shared.config); + if let Some(ext_addr) = base.nat_traversal(&original_listened_addr, &info.observed_addr) { + let mut listened_addrs = shared.listened_addrs.write(); + if !listened_addrs.iter().any(|a| a == &ext_addr) { + trace!(target: "sub-libp2p", "NAT traversal: remote observes us as \ + {} ; registering {} as one of our own addresses", + info.observed_addr, ext_addr); + listened_addrs.push(ext_addr); + } + } + for addr in info.info.listen_addrs.iter() { + trace!(target: "sub-libp2p", "Peer store: adding address {} for {:?}", + addr, peer_id); + shared.network_state.add_kad_discovered_addr(&peer_id, addr.clone()); + } + + info + }); + + let out = TransportOutput { + socket: out.socket, + info: Box::new(info) as Box<_>, + original_addr: out.original_addr, + }; + + future::ok((out, remote_addr)) + } + }) + }; + + // Build the swarm. The swarm is the single entry point where successfully negotiated protocols + // arrive. + let (swarm_controller, swarm_future) = { + let upgraded_transport = transport.clone() + .and_then({ + let kad_upgrade = kad_upgrade.clone(); + let shared = shared.clone(); + move |out, endpoint, client_addr| { + let original_addr = out.original_addr; + let listener_upgrade = upgrade::or(upgrade::or(upgrade::or( + upgrade::map(kad_upgrade.clone(), FinalUpgrade::Kad), + upgrade::map(IdentifyProtocolConfig, |id| FinalUpgrade::Identify(id, original_addr))), + upgrade::map(ping::Ping, |(p, f)| FinalUpgrade::Ping(p, f))), + upgrade::map(DelayedProtosList(shared), FinalUpgrade::Custom)); + upgrade::apply(out.socket, listener_upgrade, endpoint, client_addr) + } + }) + .map(|out, _| (out, Endpoint::Listener)); + let shared = shared.clone(); + + libp2p::core::swarm( + upgraded_transport, + move |(upgrade, endpoint), client_addr| { + listener_handle(shared.clone(), upgrade, endpoint, local_public_key.clone(), client_addr) + }, + ) + }; + + // Listen on multiaddress. + // TODO: change the network config to directly contain a `Multiaddr` + { + let listen_addr = config_to_listen_addr(&shared.config); + debug!(target: "sub-libp2p", "Libp2p listening on {}", listen_addr); + if let Err(_) = swarm_controller.listen_on(listen_addr.clone()) { + warn!(target: "sub-libp2p", "Can't listen on {}, protocol not supported", listen_addr); + return Err(ErrorKind::BadProtocol.into()); + } + } + + // Build the timeouts system for the `register_timeout` function. + // (note: this has nothing to do with socket timeouts) + let timeouts = timeouts::build_timeouts_stream(core.clone(), timeouts_register_rx) + .for_each({ + let shared = shared.clone(); + move |(handler, protocol_id, timer_token)| { + handler.timeout(&NetworkContextImpl { + inner: shared.clone(), + protocol: protocol_id, + current_peer: None, + }, timer_token); + Ok(()) + } + }); + + // Start the process of periodically discovering nodes to connect to. + let discovery = start_kademlia_discovery(shared.clone(), transport, local_peer_id, + swarm_controller, kad_config, kad_upgrade); + + // Merge all the futures into one! + Ok(swarm_future + .select(discovery).map_err(|(err, _)| err).and_then(|(_, rest)| rest) + .select(timeouts).map_err(|(err, _)| err).and_then(|(_, rest)| rest) + .select(close_rx.then(|_| Ok(()))).map(|_| ()).map_err(|(err, _)| err) + + .and_then(move |_| { + debug!(target: "sub-libp2p", "Networking ended ; disconnecting all peers"); + shared.network_state.disconnect_all(); + Ok(()) + })) +} + +// Output of the common transport layer. +struct TransportOutput { + socket: S, + info: Box>, + original_addr: Multiaddr, +} + +// Enum of all the possible protocols our service handles. +enum FinalUpgrade { + Kad(KademliaPeerReqStream), + // The remote identification system, and the multiaddress we see the remote as. + Identify(IdentifyOutput, Multiaddr), + Ping(ping::Pinger, Box>), + // `Custom` means anything not in the core libp2p and is handled + // by `CustomProtoConnectionUpgrade`. + Custom(RegisteredProtocolOutput>), +} + +// Called whenever we successfully open a multistream with a remote. +fn listener_handle<'a, C>(shared: Arc, upgrade: FinalUpgrade, endpoint: Endpoint, + local_public_key: libp2p::core::PublicKey, + client_addr: impl Future + 'a, + /*listener_upgrade: impl ConnectionUpgrade>>*/) + -> Box + 'a> +where C: AsyncRead + AsyncWrite + 'a +{ + match upgrade { + FinalUpgrade::Kad(kademlia_stream) => { + trace!(target: "sub-libp2p", "Opened kademlia substream with remote as {:?}", endpoint); + let shared = shared.clone(); + Box::new(kademlia_stream.for_each(move |req| { + let shared = shared.clone(); + let response = req + .requested_peers() + .map(move |peer_id| { + let addrs = shared.network_state.addrs_of_peer(peer_id); + let connec_ty = if shared.network_state.has_connection(&peer_id) { + // TODO: this only checks connections with substrate ; but what if + // we're connected through Kad only? + ConnectionType::Connected + } else { + ConnectionType::NotConnected + }; + + Peer { + node_id: peer_id.clone(), + multiaddrs: addrs, + connection_ty: connec_ty, + } + }) + .collect::>(); + req.respond(response); + Ok(()) + })) + }, + + FinalUpgrade::Identify(IdentifyOutput::Sender { sender }, original_addr) => { + trace!(target: "sub-libp2p", "Sending back identification info"); + /*let protocols_to_report = ConnectionUpgrade::<_, Box>>::protocol_names(&listener_upgrade) + .filter_map(|(name, _)| String::from_utf8(name.to_vec()).ok()) + .collect();*/ + sender.send( + IdentifyInfo { + public_key: local_public_key.clone(), + protocol_version: concat!("substrate/", env!("CARGO_PKG_VERSION")).to_owned(), + agent_version: "rust-libp2p/1.0.0".to_owned(), + listen_addrs: shared.listened_addrs.read().clone(), + protocols: Vec::new(), // TODO: protocols_to_report, + }, + &original_addr + ) + }, + + FinalUpgrade::Identify(IdentifyOutput::RemoteInfo { .. }, _) => { + unreachable!("We are never dialing with the identify protocol") + }, + + FinalUpgrade::Ping(_pinger, future) => { + future + }, + + FinalUpgrade::Custom(custom_proto_out) => { + // A "custom" protocol is one that is part of substrate and not part of libp2p. + let shared = shared.clone(); + Box::new(client_addr.and_then(move |client_addr| { + let handler = custom_proto_out.custom_data; + let protocol_id = custom_proto_out.protocol_id; + + // We're using the `PeerIdTransport` layer, so all the multiaddresses received + // here should be of the format `/p2p/`. + let node_id = { + let (first, second); + { + let mut iter = client_addr.iter(); + first = iter.next(); + second = iter.next(); + } + match (first, second) { + (Some(AddrComponent::P2P(node_id)), None) => { + PeerstorePeerId::from_bytes(node_id) + .expect("libp2p always reports a valid node id") + }, + _ => panic!("Reported multiaddress is in the wrong format ; \ + programmer error") + } + }; + + // Determine the ID of this peer, or drop the connection if the peer is disabled, + // if we reached `max_peers`, or a similar reason. + // TODO: is there a better way to refuse connections than to drop the + // newly-opened substream? should we refuse the connection + // beforehand? + let peer_id = match shared.network_state.accept_connection(node_id.clone(), protocol_id, custom_proto_out.protocol_version, endpoint, custom_proto_out.outgoing) { + Ok(peer_id) => peer_id, + Err(err) => return future::Either::A(future::err(err.into())), + }; + + debug!(target: "sub-libp2p", "Successfully connected to {:?} (peer id \ + {}) with protocol {:?} version {}", + node_id, peer_id, protocol_id, custom_proto_out.protocol_version); + handler.connected(&NetworkContextImpl { + inner: shared.clone(), + protocol: protocol_id, + current_peer: Some(peer_id), + }, &peer_id); + + future::Either::B(custom_proto_out + .incoming + .for_each({ + let handler = handler.clone(); + let shared = shared.clone(); + move |(packet_id, data)| { + trace!(target: "sub-libp2p", "Received message of len {} from peer {}", + data.len(), peer_id); + handler.read(&NetworkContextImpl { + inner: shared.clone(), + protocol: protocol_id, + current_peer: Some(peer_id.clone()), + }, &peer_id, packet_id, &data); + Ok(()) + } + }) + .then(move |val| { + debug!(target: "sub-libp2p", "Node {:?} with peer ID {} \ + through protocol {:?} disconnected", node_id, peer_id, + protocol_id); + handler.disconnected(&NetworkContextImpl { + inner: shared.clone(), + protocol: protocol_id, + current_peer: Some(peer_id), + }, &peer_id); + + // When any custom protocol drops, we drop the peer entirely. + // TODO: is this correct? + shared.network_state.disconnect_peer(peer_id); + val + })) + })) as Box<_> + }, + } +} + +// Builds the multiaddress corresponding to the address we need to listen to according to the +// config. +// TODO: put the `Multiaddr` directly in the `NetworkConfiguration` +fn config_to_listen_addr(config: &NetworkConfiguration) -> Multiaddr { + if let Some(addr) = config.listen_address { + let ip = match addr.ip() { + IpAddr::V4(addr) => AddrComponent::IP4(addr), + IpAddr::V6(addr) => AddrComponent::IP6(addr), + }; + iter::once(ip).chain(iter::once(AddrComponent::TCP(addr.port()))).collect() + } else { + let host = AddrComponent::IP4(Ipv4Addr::new(0, 0, 0, 0)); + let port = AddrComponent::TCP(0); + iter::once(host).chain(iter::once(port)).collect() + } +} + +// Randomly discovers peers to connect to. +// This works by running a round at a regular interval, and skipping if we reached `min_peers`. +// When we are over `min_peers`, we stop trying to dial nodes and only accept incoming +// connections. +fn start_kademlia_discovery(shared: Arc, transport: T, local_peer_id: PeerstorePeerId, + swarm_controller: SwarmController, + kad_config: KademliaControllerPrototype, + kad_upgrade: KademliaUpgrade) -> impl Future +where T: MuxedTransport> + Clone + 'static, + T::MultiaddrFuture: 'static, + To: AsyncRead + AsyncWrite + 'static, + St: MuxedTransport, Endpoint)> + Clone + 'static, + C: 'static, +{ + let (kad_controller, kad_future) = { + let trans = transport.clone() + .and_then(|out, endpoint, client_addr| { + upgrade::apply(out.socket, kad_upgrade, endpoint, client_addr) + }); + kad_config.start(swarm_controller.clone(), trans, |kad| { + (FinalUpgrade::Kad(kad), Endpoint::Dialer) + }) + }; + + let discovery = tokio_timer::wheel() + .build() + .interval_at(Instant::now(), Duration::from_secs(30)) + // TODO: add a timeout to the lookups + .map_err(|_| -> IoError { unreachable!() }) + .and_then({ + let shared = shared.clone(); + move |()| { + if shared.network_state.should_open_outgoing_connecs() { + // Query the node IDs that are closest to a random ID. + // Note that the randomness doesn't have to be secure, as this only influences + // which nodes we end up being connected to. + let random_key = PublicKey::Ed25519((0 .. 32).map(|_| -> u8 { rand::random() }).collect()); + let random_peer_id = random_key.into_peer_id(); + trace!(target: "sub-libp2p", "Start kademlia discovery for {:?}", + random_peer_id); + let shared = shared.clone(); + future::Either::A(kad_controller + .find_node(random_peer_id) + .filter_map(move |event| { + match event { + QueryEvent::NewKnownMultiaddrs(peers) => { + for (peer, addrs) in peers { + trace!(target: "sub-libp2p", "Peer store: adding addresses {:?} for {:?}", + addrs, peer); + for addr in addrs { + shared.network_state.add_kad_discovered_addr(&peer, addr); + } + } + None + }, + QueryEvent::Finished(out) => Some(out), + } + }) + .into_future() + .map_err(|(err, _)| err) + .map(|(out, _)| out.unwrap())) + } else { + // If we reached `min_peers`, pretend we did a lookup but with an empty result. + trace!(target: "sub-libp2p", "Bypassing kademlia discovery"); + future::Either::B(future::ok(Vec::new())) + } + } + }) + .for_each({ + let shared = shared.clone(); + move |results| { + trace!(target: "sub-libp2p", "Processing Kademlia discovery results"); + + // It's possible that `reserved_only` got set to true while the query was resolving. + if results.is_empty() || shared.network_state.is_reserved_only() { + return Ok(()); + } + + for discovered_peer in results { + // Skip if we reach `min_peers`. + // Also skip nodes we are already connected to, in order to not connect twice. + if !shared.network_state.should_open_outgoing_connecs() || + discovered_peer == local_peer_id || + shared.network_state.has_connection(&discovered_peer) || + shared.network_state.is_peer_disabled(&discovered_peer) + { + trace!(target: "sub-libp2p", "Skipping discovered peer {:?}", discovered_peer); + continue; + } + + let addr: Multiaddr = AddrComponent::P2P(discovered_peer.clone().into_bytes()).into(); + // Try to dial that node for each registered protocol. Since dialing upgrades + // the connection to use multiplexing, dialing multiple times should + // automatically open multiple substreams. + trace!(target: "sub-libp2p", "Dialing node {:?} for each protocol", addr); + for proto in shared.protocols.read().0.clone().into_iter() { + // TODO: check that the secio key matches the id given by kademlia + let proto_id = proto.id(); + let discovered_peer = discovered_peer.clone(); + let with_proto = transport.clone() + .and_then(move |out, endpoint, client_addr| { + let socket = out.socket; + out.info + .and_then(move |info| { + if info.info.public_key.into_peer_id() == discovered_peer { + Ok(socket) + } else { + debug!(target: "sub-libp2p", "Interrupted dialing node {:?} for proto {:?} because its reported public key doesn't match the Kademlia entry", discovered_peer, proto_id); + Err(IoErrorKind::InvalidData.into()) // TODO: correct err + } + }) + .and_then(move |socket| { + upgrade::apply(socket, proto, endpoint, client_addr) + }) + }) + .and_then(move |out, endpoint, client_addr| { + future::ok(((FinalUpgrade::Custom(out), endpoint), client_addr)) + }); + if let Err(err) = swarm_controller.dial(addr.clone(), with_proto) { + warn!(target: "sub-libp2p", "Error while dialing {}: {:?}", addr, err); + } + } + } + + Ok(()) + } + }); + + kad_future + .select(discovery) + .map_err(|(err, _)| err) + .and_then(|(_, rest)| rest) +} + +// Since new protocols are added after the networking starts, we have to load the protocols list +// in a lazy way. This is what this wrapper does. +#[derive(Clone)] +struct DelayedProtosList(Arc); +impl ConnectionUpgrade for DelayedProtosList +where C: AsyncRead + AsyncWrite + 'static, // TODO: 'static :-/ + Maf: Future + 'static, // TODO: 'static :( +{ + type NamesIter = > as ConnectionUpgrade>::NamesIter; + type UpgradeIdentifier = > as ConnectionUpgrade>::UpgradeIdentifier; + + fn protocol_names(&self) -> Self::NamesIter { + ConnectionUpgrade::::protocol_names(&*self.0.protocols.read()) + } + + type Output = > as ConnectionUpgrade>::Output; + type MultiaddrFuture = > as ConnectionUpgrade>::MultiaddrFuture; + type Future = > as ConnectionUpgrade>::Future; + + #[inline] + fn upgrade(self, socket: C, id: Self::UpgradeIdentifier, endpoint: Endpoint, + remote_addr: Maf) -> Self::Future + { + self.0.protocols.read() + .clone() + .upgrade(socket, id, endpoint, remote_addr) + } +} + +#[cfg(test)] +mod tests { + use super::NetworkService; + + #[test] + fn builds_and_finishes_in_finite_time() { + // Checks that merely starting the network doesn't end up in an infinite loop. + let service = NetworkService::new(Default::default(), None).unwrap(); + service.start().map_err(|(err, _)| err).unwrap(); + } +} diff --git a/substrate/network-libp2p/src/timeouts.rs b/substrate/network-libp2p/src/timeouts.rs new file mode 100644 index 0000000000000..c0bec870b0edb --- /dev/null +++ b/substrate/network-libp2p/src/timeouts.rs @@ -0,0 +1,87 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see .? + +use futures::{future, Future, stream, Stream}; +use std::io::Error as IoError; +use std::time::Instant; +use tokio_core::reactor::{Handle, Timeout}; + +/// Builds the timeouts system. +/// +/// The `timeouts_rx` should be a stream receiving newly-created timeout requests. +/// Returns a stream that produces items as their timeout elapses. +/// `T` can be anything you want, as it is transparently passed from the input to the output. +pub fn build_timeouts_stream(core: Handle, timeouts_rx: impl Stream) + -> impl Stream +{ + let next_timeout = next_in_timeouts_stream(timeouts_rx); + + // The `unfold` function is essentially a loop turned into a stream. The first parameter is + // the initial state, and the closure returns the new state and an item. + stream::unfold(vec![future::Either::A(next_timeout)], move |timeouts| { + // `timeouts` is a `Vec` of futures that produce an `Out`. + + let core = core.clone(); + + // `select_ok` panics if `timeouts` is empty anyway. + if timeouts.is_empty() { + return None; + } + + Some(future::select_ok(timeouts.into_iter()) + .and_then(move |(item, mut timeouts)| { + match item { + Out::NewTimeout((Some((at, item)), next_timeouts)) => { + // Received a new timeout request on the channel. + let next_timeout = next_in_timeouts_stream(next_timeouts); + let timeout = Timeout::new_at(at, &core)? + .map(move |()| Out::Timeout(item)); + timeouts.push(future::Either::B(timeout)); + timeouts.push(future::Either::A(next_timeout)); + Ok((None, timeouts)) + }, + Out::NewTimeout((None, _)) => { + // The channel has been closed. + Ok((None, timeouts)) + }, + Out::Timeout(item) => { + // A timeout has happened. + Ok((Some(item), timeouts)) + }, + } + })) + }).filter_map(|item| item) +} + +// Local enum representing the output of the selection. +enum Out { + NewTimeout(A), + Timeout(B), +} + +// Convenience function that calls `.into_future()` on the timeouts stream, and applies some +// modifiers. +// This function is necessary. Otherwise if we copy-paste its content we run into errors because +// the type of the copy-pasted closures differs. +fn next_in_timeouts_stream(stream: S) + -> impl Future, S), B>, Error = IoError> +where S: Stream +{ + stream + .into_future() + .map(Out::NewTimeout) + .map_err(|_| unreachable!()) +} diff --git a/substrate/network-libp2p/src/transport.rs b/substrate/network-libp2p/src/transport.rs new file mode 100644 index 0000000000000..922e1646b566b --- /dev/null +++ b/substrate/network-libp2p/src/transport.rs @@ -0,0 +1,37 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see .? + +use libp2p::{self, Transport, core::MuxedTransport}; +use tokio_core::reactor::Handle; +use tokio_io::{AsyncRead, AsyncWrite}; + +/// Builds the transport that serves as a common ground for all connections. +pub fn build_transport(core: Handle) -> impl MuxedTransport + Clone { + libp2p::CommonTransport::new(core) + .with_upgrade({ + /*secio::SecioConfig { + key: local_private_key, + }*/ + // TODO: we temporarily use plaintext/1.0.0 in order to make testing easier + libp2p::core::upgrade::PlainTextConfig + }) + .map(|socket /*(socket, key)*/, _| { + // TODO: check that the public key matches what is reported by identify + socket + }) + .with_upgrade(libp2p::mplex::MultiplexConfig::new()) + .into_connection_reuse() +} diff --git a/substrate/network-libp2p/tests/tests.rs b/substrate/network-libp2p/tests/tests.rs new file mode 100644 index 0000000000000..4486d9343cbdf --- /dev/null +++ b/substrate/network-libp2p/tests/tests.rs @@ -0,0 +1,151 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +#[macro_use] +extern crate log; +extern crate parking_lot; +extern crate ethcore_bytes; +extern crate ethcore_io as io; +extern crate ethcore_logger; +extern crate ethcore_network; +extern crate substrate_network_libp2p; +extern crate ethkey; + +use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering}; +use std::sync::Arc; +use std::thread; +use std::time::*; +use parking_lot::Mutex; +use ethcore_bytes::Bytes; +use ethcore_network::*; +use substrate_network_libp2p::NetworkService; +use ethkey::{Random, Generator}; +use io::TimerToken; + +pub struct TestProtocol { + drop_session: bool, + pub packet: Mutex, + pub got_timeout: AtomicBool, + pub got_disconnect: AtomicBool, +} + +impl TestProtocol { + pub fn new(drop_session: bool) -> Self { + TestProtocol { + packet: Mutex::new(Vec::new()), + got_timeout: AtomicBool::new(false), + got_disconnect: AtomicBool::new(false), + drop_session: drop_session, + } + } + /// Creates and register protocol with the network service + pub fn register(service: &mut NetworkService, drop_session: bool) -> Arc { + let handler = Arc::new(TestProtocol::new(drop_session)); + service.register_protocol(handler.clone(), *b"tst", &[(42u8, 1), (43u8, 1)]); + handler + } + + pub fn got_packet(&self) -> bool { + self.packet.lock()[..] == b"hello"[..] + } + + pub fn got_timeout(&self) -> bool { + self.got_timeout.load(AtomicOrdering::Relaxed) + } + + pub fn got_disconnect(&self) -> bool { + self.got_disconnect.load(AtomicOrdering::Relaxed) + } +} + +impl NetworkProtocolHandler for TestProtocol { + fn initialize(&self, io: &NetworkContext) { + io.register_timer(0, Duration::from_millis(10)).unwrap(); + } + + fn read(&self, _io: &NetworkContext, _peer: &PeerId, packet_id: u8, data: &[u8]) { + assert_eq!(packet_id, 33); + self.packet.lock().extend(data); + } + + fn connected(&self, io: &NetworkContext, peer: &PeerId) { + assert!(io.peer_client_version(*peer).contains("Parity")); + if self.drop_session { + io.disconnect_peer(*peer) + } else { + io.respond(33, "hello".to_owned().into_bytes()).unwrap(); + } + } + + fn disconnected(&self, _io: &NetworkContext, _peer: &PeerId) { + self.got_disconnect.store(true, AtomicOrdering::Relaxed); + } + + /// Timer function called after a timeout created with `NetworkContext::timeout`. + fn timeout(&self, _io: &NetworkContext, timer: TimerToken) { + assert_eq!(timer, 0); + self.got_timeout.store(true, AtomicOrdering::Relaxed); + } +} + + +#[test] +fn net_service() { + let service = NetworkService::new(NetworkConfiguration::new_local(), None).expect("Error creating network service"); + service.start().unwrap(); + service.register_protocol(Arc::new(TestProtocol::new(false)), *b"myp", &[(1u8, 1)]); +} + +#[test] +fn net_start_stop() { + let config = NetworkConfiguration::new_local(); + let service = NetworkService::new(config, None).unwrap(); + service.start().unwrap(); + service.stop(); + service.start().unwrap(); +} + +#[test] +fn net_disconnect() { + let key1 = Random.generate().unwrap(); + let mut config1 = NetworkConfiguration::new_local(); + config1.use_secret = Some(key1.secret().clone()); + config1.boot_nodes = vec![ ]; + let mut service1 = NetworkService::new(config1, None).unwrap(); + service1.start().unwrap(); + let handler1 = TestProtocol::register(&mut service1, false); + let mut config2 = NetworkConfiguration::new_local(); + config2.boot_nodes = vec![ service1.external_url().unwrap() ]; + let mut service2 = NetworkService::new(config2, None).unwrap(); + service2.start().unwrap(); + let handler2 = TestProtocol::register(&mut service2, true); + while !(handler1.got_disconnect() && handler2.got_disconnect()) { + thread::sleep(Duration::from_millis(50)); + } + assert!(handler1.got_disconnect()); + assert!(handler2.got_disconnect()); +} + +#[test] +fn net_timeout() { + let config = NetworkConfiguration::new_local(); + let mut service = NetworkService::new(config, None).unwrap(); + service.start().unwrap(); + let handler = TestProtocol::register(&mut service, false); + while !handler.got_timeout() { + thread::sleep(Duration::from_millis(50)); + } +} diff --git a/substrate/network/Cargo.toml b/substrate/network/Cargo.toml index bd132992f8971..133956b35f943 100644 --- a/substrate/network/Cargo.toml +++ b/substrate/network/Cargo.toml @@ -19,7 +19,6 @@ serde_json = "1.0" futures = "0.1.17" linked-hash-map = "0.5" ethcore-network = { git = "https://github.com/paritytech/parity.git" } -ethcore-network-devp2p = { git = "https://github.com/paritytech/parity.git" } ethcore-io = { git = "https://github.com/paritytech/parity.git" } ed25519 = { path = "../../substrate/ed25519" } substrate-primitives = { path = "../../substrate/primitives" } @@ -30,6 +29,7 @@ substrate-runtime-support = { path = "../../substrate/runtime-support" } substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" } substrate-bft = { path = "../../substrate/bft" } substrate-codec = { path = "../../substrate/codec" } +substrate-network-libp2p = { path = "../../substrate/network-libp2p" } [dev-dependencies] env_logger = "0.4" diff --git a/substrate/network/src/lib.rs b/substrate/network/src/lib.rs index 15779ea6522cd..0a39b0e1c550b 100644 --- a/substrate/network/src/lib.rs +++ b/substrate/network/src/lib.rs @@ -19,7 +19,6 @@ //! Implements polkadot protocol version as specified here: //! https://github.com/paritytech/polkadot/wiki/Network-protocol -extern crate ethcore_network_devp2p as network_devp2p; extern crate ethcore_network as network; extern crate ethcore_io as core_io; extern crate linked_hash_map; @@ -31,6 +30,7 @@ extern crate substrate_serializer as ser; extern crate substrate_client as client; extern crate substrate_runtime_support as runtime_support; extern crate substrate_runtime_primitives as runtime_primitives; +extern crate substrate_network_libp2p as network_libp2p; extern crate substrate_bft; extern crate substrate_codec as codec; extern crate serde; diff --git a/substrate/network/src/service.rs b/substrate/network/src/service.rs index f26e31337da74..222ce5b044baa 100644 --- a/substrate/network/src/service.rs +++ b/substrate/network/src/service.rs @@ -21,7 +21,7 @@ use std::time::Duration; use futures::sync::{oneshot, mpsc}; use network::{NetworkProtocolHandler, NetworkContext, PeerId, ProtocolId, NetworkConfiguration , NonReservedPeerMode, ErrorKind}; -use network_devp2p::{NetworkService}; +use network_libp2p::{NetworkService}; use core_io::{TimerToken}; use io::NetSyncIo; use protocol::{Protocol, ProtocolStatus, PeerInfo as ProtocolPeerInfo}; @@ -181,8 +181,7 @@ impl Service where B::Header: HeaderT { Err(err) => warn!("Error starting network: {}", err), _ => {}, }; - self.network.register_protocol(self.handler.clone(), DOT_PROTOCOL_ID, &[(0, V0_PACKET_COUNT)]) - .unwrap_or_else(|e| warn!("Error registering polkadot protocol: {:?}", e)); + self.network.register_protocol(self.handler.clone(), DOT_PROTOCOL_ID, &[(0, V0_PACKET_COUNT)]); } fn stop(&self) {