diff --git a/Cargo.lock b/Cargo.lock index a33cd951311ed..84f19567f6d45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,7 +17,7 @@ dependencies = [ "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.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -252,11 +252,11 @@ dependencies = [ [[package]] name = "cid" version = "0.2.3" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "multihash 0.8.1-pre (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", ] [[package]] @@ -401,13 +401,13 @@ dependencies = [ [[package]] name = "datastore" version = "0.1.0" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -569,14 +569,6 @@ 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" @@ -971,7 +963,7 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1116,26 +1108,26 @@ 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=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "libp2p-dns 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "libp2p-floodsub 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "libp2p-identify 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "libp2p-kad 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "libp2p-mplex 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "libp2p-ping 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "libp2p-ratelimit 0.1.1 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "libp2p-relay 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "libp2p-secio 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "libp2p-tcp-transport 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "libp2p-transport-timeout 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "libp2p-websocket 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "libp2p-yamux 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "libp2p-dns 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "libp2p-floodsub 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "libp2p-identify 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "libp2p-kad 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "libp2p-mplex 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "libp2p-ping 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "libp2p-ratelimit 0.1.1 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "libp2p-relay 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "libp2p-secio 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "libp2p-tcp-transport 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "libp2p-transport-timeout 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "libp2p-websocket 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "libp2p-yamux 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "stdweb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1145,20 +1137,20 @@ dependencies = [ [[package]] name = "libp2p-core" version = "0.1.0" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "multihash 0.8.1-pre (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "multistream-select 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "multihash 0.8.1-pre (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "multistream-select 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "rw-stream-sink 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "smallvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1166,12 +1158,12 @@ dependencies = [ [[package]] name = "libp2p-dns" version = "0.1.0" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "tokio-dns-unofficial 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1179,96 +1171,96 @@ dependencies = [ [[package]] name = "libp2p-floodsub" version = "0.1.0" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "unsigned-varint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-identify" version = "0.1.0" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "unsigned-varint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-kad" version = "0.1.0" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "datastore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "libp2p-identify 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "libp2p-ping 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "libp2p-identify 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "libp2p-ping 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.0.3 (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.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "tokio-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-mplex" version = "0.1.0" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "unsigned-varint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-peerstore" version = "0.1.0" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "datastore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1277,14 +1269,14 @@ dependencies = [ [[package]] name = "libp2p-ping" version = "0.1.0" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "multistream-select 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "multistream-select 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1294,11 +1286,11 @@ dependencies = [ [[package]] name = "libp2p-ratelimit" version = "0.1.1" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "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.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1307,37 +1299,37 @@ dependencies = [ [[package]] name = "libp2p-relay" version = "0.1.0" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "protobuf 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "unsigned-varint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-secio" version = "0.1.0" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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)", "eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.0.3 (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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "rw-stream-sink 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1345,12 +1337,12 @@ dependencies = [ [[package]] name = "libp2p-tcp-transport" version = "0.1.0" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "tk-listen 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1359,24 +1351,24 @@ dependencies = [ [[package]] name = "libp2p-transport-timeout" version = "0.1.0" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-websocket" version = "0.1.0" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", - "rw-stream-sink 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", + "rw-stream-sink 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "stdweb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "websocket 0.20.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1385,11 +1377,11 @@ dependencies = [ [[package]] name = "libp2p-yamux" version = "0.1.0" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "yamux 0.1.0 (git+https://github.com/paritytech/yamux)", @@ -1523,10 +1515,10 @@ dependencies = [ [[package]] name = "multiaddr" version = "0.3.0" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "cid 0.2.3 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "integer-encoding 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1541,7 +1533,7 @@ dependencies = [ [[package]] name = "multihash" version = "0.8.1-pre" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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)", @@ -1551,14 +1543,14 @@ dependencies = [ [[package]] name = "multistream-select" version = "0.1.0" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "varint 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "unsigned-varint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1603,15 +1595,6 @@ 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" @@ -2102,7 +2085,7 @@ dependencies = [ [[package]] name = "rw-stream-sink" version = "0.1.0" -source = "git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" +source = "git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779#5159f3aeae2ba6cc7015c511816a5f965c444779" 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)", @@ -2191,7 +2174,7 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2270,7 +2253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2524,7 +2507,7 @@ dependencies = [ "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2580,14 +2563,17 @@ dependencies = [ "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)", "libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)", + "libp2p 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "unsigned-varint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2800,7 +2786,7 @@ dependencies = [ "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-codec-derive 0.1.0", "substrate-primitives 0.1.0", @@ -2943,7 +2929,7 @@ name = "substrate-serializer" version = "0.1.0" dependencies = [ "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2958,7 +2944,7 @@ dependencies = [ "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-client 0.1.0", "substrate-client-db 0.1.0", @@ -3197,7 +3183,7 @@ dependencies = [ "tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3226,7 +3212,7 @@ dependencies = [ "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3343,7 +3329,7 @@ dependencies = [ [[package]] name = "tokio-timer" -version = "0.2.4" +version = "0.2.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)", @@ -3545,19 +3531,6 @@ 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/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294#6aa139a12dbea3d75d898ce0b2af7fcec129e294" -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.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "vcpkg" version = "0.2.3" @@ -3585,7 +3558,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", "wabt-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3752,7 +3725,7 @@ dependencies = [ "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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" +"checksum cid 0.2.3 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "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" @@ -3769,7 +3742,7 @@ dependencies = [ "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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" +"checksum datastore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" "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" @@ -3777,7 +3750,6 @@ dependencies = [ "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" @@ -3836,22 +3808,22 @@ dependencies = [ "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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" -"checksum libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" -"checksum libp2p-dns 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" -"checksum libp2p-floodsub 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" -"checksum libp2p-identify 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" -"checksum libp2p-kad 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" -"checksum libp2p-mplex 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" -"checksum libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" -"checksum libp2p-ping 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" -"checksum libp2p-ratelimit 0.1.1 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" -"checksum libp2p-relay 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" -"checksum libp2p-secio 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" -"checksum libp2p-tcp-transport 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" -"checksum libp2p-transport-timeout 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" -"checksum libp2p-websocket 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" -"checksum libp2p-yamux 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" +"checksum libp2p 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" +"checksum libp2p-core 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" +"checksum libp2p-dns 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" +"checksum libp2p-floodsub 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" +"checksum libp2p-identify 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" +"checksum libp2p-kad 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" +"checksum libp2p-mplex 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" +"checksum libp2p-peerstore 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" +"checksum libp2p-ping 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" +"checksum libp2p-ratelimit 0.1.1 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" +"checksum libp2p-relay 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" +"checksum libp2p-secio 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" +"checksum libp2p-tcp-transport 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" +"checksum libp2p-transport-timeout 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" +"checksum libp2p-websocket 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" +"checksum libp2p-yamux 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" "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" @@ -3867,16 +3839,15 @@ dependencies = [ "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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" +"checksum multiaddr 0.3.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" "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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" -"checksum multistream-select 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" +"checksum multihash 0.8.1-pre (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" +"checksum multistream-select 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" "checksum names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef320dab323286b50fb5cdda23f61c796a72a89998ab565ca32525c5c556f2da" "checksum nan-preserving-float 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34d4f00fcc2f4c9efa8cc971db0da9e28290e28e97af47585e48691ef10ff31f" "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.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" @@ -3933,7 +3904,7 @@ dependencies = [ "checksum rustc-hex 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b03280c2813907a030785570c577fb27d3deec8da4c18566751ade94de0ace" "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=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" +"checksum rw-stream-sink 0.1.0 (git+https://github.com/tomaka/libp2p-rs?rev=5159f3aeae2ba6cc7015c511816a5f965c444779)" = "" "checksum safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f7bf422d23a88c16d5090d455f182bc99c60af4df6a345c63428acf5129e347" "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" @@ -3945,7 +3916,7 @@ dependencies = [ "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "0c3adf19c07af6d186d91dae8927b83b0553d07ca56cbf7f2f32560455c91920" "checksum serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "3525a779832b08693031b8ecfb0de81cd71cfd3812088fafe9a7496789572124" -"checksum serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "84b8035cabe9b35878adec8ac5fe03d5f6bc97ff6edd7ccb96b44c1276ba390e" +"checksum serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c6908c7b925cd6c590358a4034de93dbddb20c45e1d021931459fd419bf0e2" "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" @@ -3993,7 +3964,7 @@ dependencies = [ "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.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c3873a6d8d0b636e024e77b9a82eaab6739578a06189ecd0e731c7308fbc5d" -"checksum tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "028b94314065b90f026a21826cffd62a4e40a92cda3e5c069cc7b02e5945f5e9" +"checksum tokio-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1c76b4e97a4f61030edff8bd272364e4f731b9f54c7307eb4eb733c3926eb96a" "checksum tokio-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "772f4b04e560117fe3b0a53e490c16ddc8ba6ec437015d91fa385564996ed913" "checksum tokio-udp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "137bda266504893ac4774e0ec4c2108f7ccdbcb7ac8dced6305fe9e4e0b5041a" "checksum trace-time 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5aea07da6582e957c6e737eeb63a5af79e648eeeaaaba8fd9a417f1124bafa41" @@ -4019,7 +3990,6 @@ dependencies = [ "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/tomaka/libp2p-rs?rev=6aa139a12dbea3d75d898ce0b2af7fcec129e294)" = "" "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" diff --git a/substrate/network-libp2p/Cargo.toml b/substrate/network-libp2p/Cargo.toml index 2ff26882e6fbc..c3af6aa8413ed 100644 --- a/substrate/network-libp2p/Cargo.toml +++ b/substrate/network-libp2p/Cargo.toml @@ -11,8 +11,7 @@ bytes = "0.4" error-chain = { version = "0.12", default-features = false } fnv = "1.0" futures = "0.1" -# libp2p = { git = "https://github.com/tomaka/libp2p-rs", branch = "polkadot-2", default-features = false, features = ["libp2p-secio", "libp2p-secio-secp256k1"] } -libp2p = { git = "https://github.com/tomaka/libp2p-rs", rev = "6aa139a12dbea3d75d898ce0b2af7fcec129e294", default-features = false, features = ["libp2p-secio", "libp2p-secio-secp256k1"] } +libp2p = { git = "https://github.com/libp2p/rust-libp2p", rev = "02576eecf140a06134519ed9438d061d99bb2e69", default-features = false, features = ["libp2p-secio", "libp2p-secio-secp256k1"] } ethcore-io = { git = "https://github.com/paritytech/parity.git" } ethkey = { git = "https://github.com/paritytech/parity.git" } ethereum-types = "0.3" @@ -20,10 +19,13 @@ parking_lot = "0.5" libc = "0.2" log = "0.3" rand = "0.5.0" +serde = "1.0.70" +serde_derive = "1.0.70" +serde_json = "1.0.24" tokio = "0.1" tokio-io = "0.1" tokio-timer = "0.2" -unsigned-varint = { version = "0.1", features = ["codec"] } +unsigned-varint = { version = "0.2", features = ["codec"] } [dev-dependencies] assert_matches = "1.2" diff --git a/substrate/network-libp2p/src/lib.rs b/substrate/network-libp2p/src/lib.rs index b6b358d60812a..59d056b969689 100644 --- a/substrate/network-libp2p/src/lib.rs +++ b/substrate/network-libp2p/src/lib.rs @@ -27,6 +27,10 @@ extern crate ethkey; extern crate libc; extern crate libp2p; extern crate rand; +extern crate serde; +#[macro_use] +extern crate serde_derive; +extern crate serde_json; extern crate bytes; extern crate unsigned_varint; @@ -52,6 +56,7 @@ mod error; mod network_state; mod service; mod timeouts; +mod topology; mod traits; mod transport; diff --git a/substrate/network-libp2p/src/network_state.rs b/substrate/network-libp2p/src/network_state.rs index 0ebdc4efe77bb..6226dedc347fb 100644 --- a/substrate/network-libp2p/src/network_state.rs +++ b/substrate/network-libp2p/src/network_state.rs @@ -20,20 +20,17 @@ use futures::sync::mpsc; use libp2p::core::{multiaddr::ToMultiaddr, Multiaddr, AddrComponent, Endpoint, UniqueConnec}; use libp2p::core::{UniqueConnecState, PeerId, PublicKey}; use libp2p::kad::KadConnecController; -use libp2p::peerstore::{Peerstore, PeerAccess}; -use libp2p::peerstore::json_peerstore::JsonPeerstore; -use libp2p::peerstore::memory_peerstore::MemoryPeerstore; use libp2p::ping::Pinger; use libp2p::secio; use {Error, ErrorKind, NetworkConfiguration, NonReservedPeerMode}; use {NodeIndex, ProtocolId, SessionInfo}; use parking_lot::{Mutex, RwLock}; use rand::{self, Rng}; +use topology::{DisconnectReason, NetTopology}; use std::fs; use std::io::{Error as IoError, ErrorKind as IoErrorKind, Read, Write}; use std::path::Path; use std::sync::atomic; -use std::{thread, time}; use std::time::{Duration, Instant}; // File where the peers are stored. @@ -46,7 +43,7 @@ const PEER_DISABLE_DURATION: Duration = Duration::from_secs(5 * 60); // Common struct shared throughout all the components of the service. pub struct NetworkState { /// Contains the information about the network. - node_store: NodeStore, + topology: RwLock, /// Active connections. connections: RwLock, @@ -74,13 +71,6 @@ pub struct NetworkState { local_public_key: PublicKey, } -enum NodeStore { - /// 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`. @@ -106,23 +96,24 @@ struct PeerConnectionInfo { /// Id of the peer. id: PeerId, - /// True if this connection was initiated by us. + /// True if this connection was initiated by us. `None` if we're not connected. /// 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, + originated: Option, /// Latest known ping duration. - ping: Mutex>, + ping: Option, /// 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 multiaddresses of the remote, or `None` if not known. + remote_addresses: Vec, /// The local multiaddress used to communicate with the remote, or `None` /// if not known. + // TODO: never filled ; also shouldn't be an `Option` local_address: Option, } @@ -144,7 +135,7 @@ pub struct PeerInfo { /// The client version of the remote, or `None` if not known. pub client_version: Option, - /// The multiaddress of the remote, or `None` if not known. + /// The multiaddress of the remote. pub remote_address: Option, /// The local multiaddress used to communicate with the remote, or `None` @@ -156,10 +147,10 @@ impl<'a> From<&'a PeerConnectionInfo> for PeerInfo { fn from(i: &'a PeerConnectionInfo) -> PeerInfo { PeerInfo { id: i.id.clone(), - originated: i.originated, - ping: i.ping.lock().clone(), + originated: i.originated.unwrap_or(true), + ping: i.ping, client_version: i.client_version.clone(), - remote_address: i.remote_address.clone(), + remote_address: i.remote_addresses.get(0).map(|a| a.clone()), local_address: i.local_address.clone(), } } @@ -172,39 +163,13 @@ impl NetworkState { let local_public_key = local_private_key.to_public_key(); // Build the storage for peers, including the bootstrap nodes. - let node_store = if let Some(ref path) = config.net_config_path { + let mut topology = if let Some(ref path) = config.net_config_path { let path = Path::new(path).join(NODES_FILE); - if let Ok(node_store) = JsonPeerstore::new(path.clone()) { - debug!(target: "sub-libp2p", "Initialized peer store for JSON file {:?}", path); - NodeStore::Json(node_store) - } else { - warn!(target: "sub-libp2p", "Failed to open peer storage {:?}; peers file will be reset", path); - fs::remove_file(&path).expect("Failed deleting peers.json"); - - // we check for about 1s if the file was really deleted and move on - for _x in 0..200 { - if !Path::new(&path).exists() { - break; - } else { - debug!("Waiting for effective deletion of invalid/outdate peers.json"); - thread::sleep(time::Duration::from_millis(5)); - } - } - - if let Ok(peerstore) = JsonPeerstore::new(path.clone()) { - debug!("peers.json reset"); - NodeStore::Json(peerstore) - } else { - warn!(target: "sub-libp2p", - "Failed to reset peer storage {:?}; peers change will not be saved", - path - ); - NodeStore::Memory(MemoryPeerstore::empty()) - } - } + debug!(target: "sub-libp2p", "Initializing peer store for JSON file {:?}", path); + NetTopology::from_file(path) } else { debug!(target: "sub-libp2p", "No peers file configured ; peers won't be saved"); - NodeStore::Memory(MemoryPeerstore::empty()) + NetTopology::memory() }; let reserved_peers = { @@ -213,7 +178,7 @@ impl NetworkState { Default::default() ); for peer in config.reserved_nodes.iter() { - let id = parse_and_add_to_node_store(peer, &node_store)?; + let (id, _) = parse_and_add_to_topology(peer, &mut topology)?; reserved_peers.insert(id); } RwLock::new(reserved_peers) @@ -222,7 +187,7 @@ impl NetworkState { let expected_max_peers = config.max_peers as usize + config.reserved_nodes.len(); Ok(NetworkState { - node_store, + topology: RwLock::new(topology), max_outgoing_peers: config.min_peers, max_incoming_peers: config.max_peers.saturating_sub(config.min_peers), connections: RwLock::new(Connections { @@ -248,37 +213,55 @@ impl NetworkState { &self.local_public_key } - /// Returns the ID of a random peer of the network. + /// Returns a list of peers and addresses which we should try connect to. /// - /// Returns `None` if we don't know any peer. - pub fn random_peer(&self) -> Option { - // TODO: optimize by putting the operation directly in the node_store - // https://github.com/libp2p/rust-libp2p/issues/316 - let peers = match self.node_store { - NodeStore::Memory(ref mem) => - mem.peers().collect::>(), - NodeStore::Json(ref json) => - json.peers().collect::>(), + /// Because of expiration and back-off mechanisms, this list can change + /// by itself over time. The `Instant` that is returned corresponds to + /// the earlier known time when a new entry will be added automatically to + /// the list. + pub fn outgoing_connections_to_attempt(&self) -> (Vec<(PeerId, Multiaddr)>, Instant) { + // TODO: handle better + let connections = self.connections.read(); + + let num_to_attempt = if self.reserved_only.load(atomic::Ordering::Relaxed) { + 0 + } else { + let num_open_custom_connections = num_open_custom_connections(&connections, &self.reserved_peers.read()); + self.max_outgoing_peers.saturating_sub(num_open_custom_connections.unreserved_outgoing) }; - if peers.is_empty() { - return None - } + let topology = self.topology.read(); + let (list, change) = topology.addrs_to_attempt(); + let list = list + .filter(|&(peer, _)| { + // Filter out peers which we are already connected to. + let cur = match connections.peer_by_nodeid.get(peer) { + Some(e) => e, + None => return true + }; + + let infos = match connections.info_by_peer.get(&cur) { + Some(i) => i, + None => return true + }; - let nth = rand::random::() % peers.len(); - Some(peers[nth].clone()) + !infos.protocols.iter().any(|(_, conn)| conn.is_alive()) + }) + .take(num_to_attempt as usize) + .map(|(addr, peer)| (addr.clone(), peer.clone())) + .collect(); + (list, change) } /// Returns all the IDs of the peers on the network we have knowledge of. /// /// This includes peers we are not connected to. - pub fn known_peers(&self) -> impl Iterator { - match self.node_store { - NodeStore::Memory(ref mem) => - mem.peers().collect::>().into_iter(), - NodeStore::Json(ref json) => - json.peers().collect::>().into_iter(), - } + pub fn known_peers(&self) -> Vec { + let topology = self.topology.read(); + // Note: I have no idea why, but fusing the two lines below fails the + // borrow check + let out: Vec<_> = topology.peers().cloned().collect(); + out } /// Returns true if we are connected to any peer at all. @@ -307,7 +290,7 @@ impl NetworkState { Some(info) => info, None => return, }; - *info.ping.lock() = Some(ping); + info.ping = Some(ping); } /// If we're connected to a peer with the given protocol, returns @@ -329,18 +312,15 @@ impl NetworkState { None => return None, }; - 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()), + ping: info.ping, + originated: info.originated.unwrap_or(true), + remote_address: info.remote_addresses.get(0).map(|a| a.to_string()).unwrap_or_default(), local_address: info.local_address.as_ref().map(|a| a.to_string()) .unwrap_or(String::new()), }) @@ -371,83 +351,45 @@ impl NetworkState { /// Adds an address discovered by Kademlia. /// Note that we don't have to be connected to a peer to add an address. pub fn add_kad_discovered_addr(&self, node_id: &PeerId, addr: Multiaddr) { - trace!(target: "sub-libp2p", "Peer store: adding address {} for {:?}", - addr, node_id); - match self.node_store { - NodeStore::Memory(ref mem) => - mem.peer_or_create(node_id) - .add_addr(addr, Duration::from_secs(3600)), - NodeStore::Json(ref json) => - json.peer_or_create(node_id) - .add_addr(addr, Duration::from_secs(3600)), - } - } - - /// Signals that an address doesn't match the corresponding node ID. - /// This removes the address from the peer store, so that it is not - /// returned by `addrs_of_peer` again in the future. - pub fn set_invalid_kad_address(&self, node_id: &PeerId, addr: &Multiaddr) { - // TODO: blacklist the address? - match self.node_store { - NodeStore::Memory(ref mem) => - if let Some(mut peer) = mem.peer(node_id) { - peer.rm_addr(addr.clone()) // TODO: cloning necessary? - }, - NodeStore::Json(ref json) => - if let Some(mut peer) = json.peer(node_id) { - peer.rm_addr(addr.clone()) // TODO: cloning necessary? - }, - } + self.topology.write().add_kademlia_discovered_addr(node_id, addr) } /// Returns the known multiaddresses of a peer. pub fn addrs_of_peer(&self, node_id: &PeerId) -> Vec { - match self.node_store { - NodeStore::Memory(ref mem) => - mem.peer(node_id) - .into_iter() - .flat_map(|p| p.addrs()) - .collect::>(), - NodeStore::Json(ref json) => - json.peer(node_id) - .into_iter() - .flat_map(|p| p.addrs()) - .collect::>(), - } + let topology = self.topology.read(); + // Note: I have no idea why, but fusing the two lines below fails the + // borrow check + let out: Vec = topology.addrs_of_peer(node_id).cloned().collect(); + out } /// Sets information about a peer. - pub fn set_peer_info( + /// + /// No-op if the node index is invalid. + pub fn set_node_info( &self, - node_id: PeerId, - endpoint: Endpoint, - client_version: String, - local_addr: Multiaddr, - remote_addr: Multiaddr - ) -> Result { + node_index: NodeIndex, + client_version: String + ) { let mut connections = self.connections.write(); - let who = accept_connection(&mut connections, &self.next_node_index, - node_id.clone(), endpoint)?; - let infos = connections.info_by_peer.get_mut(&who) - .expect("Newly-created peer id is always valid"); + let infos = match connections.info_by_peer.get_mut(&node_index) { + Some(i) => i, + None => return + }; infos.client_version = Some(client_version); - infos.remote_address = Some(remote_addr); - infos.local_address = Some(local_addr); - - Ok(who) } /// Adds a peer to the internal peer store. /// Returns an error if the peer address is invalid. - pub fn add_peer(&self, peer: &str) -> Result { - parse_and_add_to_node_store(peer, &self.node_store) + pub fn add_bootstrap_peer(&self, peer: &str) -> Result<(PeerId, Multiaddr), Error> { + parse_and_add_to_topology(peer, &mut self.topology.write()) } /// 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_node_store(peer, &self.node_store)?; + let (id, _) = parse_and_add_to_topology(peer, &mut self.topology.write())?; self.reserved_peers.write().insert(id); Ok(()) } @@ -456,7 +398,7 @@ impl NetworkState { /// 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_node_store(peer, &self.node_store)?; + let (id, _) = parse_and_add_to_topology(peer, &mut self.topology.write())?; self.reserved_peers.write().remove(&id); // Dropping the peer if we're in reserved mode. @@ -464,6 +406,7 @@ impl NetworkState { let mut connections = self.connections.write(); if let Some(who) = connections.peer_by_nodeid.remove(&id) { connections.info_by_peer.remove(&who); + // TODO: use drop_peer instead } } @@ -481,58 +424,168 @@ impl NetworkState { } } - /// Returns the number of new outgoing custom connections to peers to - /// open. This takes into account the number of active peers. - pub fn should_open_outgoing_custom_connections(&self) -> u32 { - if self.reserved_only.load(atomic::Ordering::Relaxed) { - 0 - } else { - let num_open_custom_connections = num_open_custom_connections(&self.connections.read(), &self.reserved_peers.read()); - self.max_outgoing_peers.saturating_sub(num_open_custom_connections.unreserved_outgoing) - } - } - /// Returns true if we are connected to the given node. pub fn has_connection(&self, node_id: &PeerId) -> bool { let connections = self.connections.read(); connections.peer_by_nodeid.contains_key(node_id) } + /// Reports that we tried to connect to the given address but failed. + /// + /// This decreases the chance this address will be tried again in the future. + #[inline] + pub fn report_failed_to_connect(&self, addr: &Multiaddr) { + trace!(target: "sub-libp2p", "Failed to connect to {:?}", addr); + self.topology.write().report_failed_to_connect(addr); + } + + /// Returns the `NodeIndex` corresponding to a node id, or assigns a `NodeIndex` if none + /// exists. + /// + /// Returns an error if this node is on the list of disabled/banned nodes.. + pub fn assign_node_index( + &self, + node_id: &PeerId + ) -> Result { + // Check whether node is disabled. + // TODO: figure out the locking strategy here to avoid possible deadlocks + // TODO: put disabled_nodes in connections? + let mut disabled_nodes = self.disabled_nodes.lock(); + if let Some(timeout) = disabled_nodes.get(node_id).cloned() { + if timeout > Instant::now() { + debug!(target: "sub-libp2p", "Refusing peer {:?} because it is disabled", node_id); + return Err(IoError::new(IoErrorKind::ConnectionRefused, "peer is disabled")); + } else { + disabled_nodes.remove(node_id); + } + } + drop(disabled_nodes); + + 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; + + let who = *peer_by_nodeid.entry(node_id.clone()).or_insert_with(|| { + let new_id = self.next_node_index.fetch_add(1, atomic::Ordering::Relaxed); + trace!(target: "sub-libp2p", "Creating new peer #{:?} for {:?}", new_id, node_id); + + info_by_peer.insert(new_id, PeerConnectionInfo { + protocols: Vec::new(), // TODO: Vec::with_capacity(num_registered_protocols), + kad_connec: UniqueConnec::empty(), + ping_connec: UniqueConnec::empty(), + id: node_id.clone(), + originated: None, + ping: None, + client_version: None, + local_address: None, + remote_addresses: Vec::with_capacity(1), + }); + + new_id + }); + + Ok(who) + } + + /// Notifies that we're connected to a node through an address. + /// + /// Returns an error if we refuse the connection. + /// + /// Note that is it legal to connection multiple times to the same node id through different + /// addresses and endpoints. + pub fn report_connected( + &self, + node_index: NodeIndex, + addr: &Multiaddr, + endpoint: Endpoint + ) -> Result<(), IoError> { + let mut connections = self.connections.write(); + + // TODO: double locking in this function ; although this has been reviewed to not deadlock + // as of the writing of this code, it is possible that a later change that isn't carefully + // reviewed triggers one + + if endpoint == Endpoint::Listener { + let stats = num_open_custom_connections(&connections, &self.reserved_peers.read()); + if stats.unreserved_incoming >= self.max_incoming_peers { + debug!(target: "sub-libp2p", "Refusing incoming connection from {} because we \ + reached max incoming peers", addr); + return Err(IoError::new(IoErrorKind::ConnectionRefused, + "maximum incoming peers reached")); + } + } + + let infos = match connections.info_by_peer.get_mut(&node_index) { + Some(i) => i, + None => return Ok(()) + }; + + if !infos.remote_addresses.iter().any(|a| a == addr) { + infos.remote_addresses.push(addr.clone()); + } + + if infos.originated.is_none() { + infos.originated = Some(endpoint == Endpoint::Dialer); + } + + self.topology.write().report_connected(addr, &infos.id); + + Ok(()) + } + + /// Returns the node id from a node index. + /// + /// Returns `None` if the node index is invalid. + pub fn node_id_from_index( + &self, + node_index: NodeIndex + ) -> Option { + let mut connections = self.connections.write(); + let infos = match connections.info_by_peer.get_mut(&node_index) { + Some(i) => i, + None => return None + }; + Some(infos.id.clone()) + } + /// Obtains the `UniqueConnec` corresponding to the Kademlia connection to a peer. + /// + /// Returns `None` if the node index is invalid. pub fn kad_connection( &self, - node_id: PeerId - ) -> Result<(NodeIndex, UniqueConnec), IoError> { - // TODO: check that the peer is disabled? should disabling a peer also prevent - // kad from working? + node_index: NodeIndex + ) -> Option> { let mut connections = self.connections.write(); - let who = accept_connection(&mut connections, &self.next_node_index, - node_id, Endpoint::Listener)?; - let infos = connections.info_by_peer.get_mut(&who) - .expect("Newly-created peer id is always valid"); - let connec = infos.kad_connec.clone(); - Ok((who, connec)) + let infos = match connections.info_by_peer.get_mut(&node_index) { + Some(i) => i, + None => return None + }; + Some(infos.kad_connec.clone()) } /// Obtains the `UniqueConnec` corresponding to the Ping connection to a peer. + /// + /// Returns `None` if the node index is invalid. pub fn ping_connection( &self, - node_id: PeerId - ) -> Result<(NodeIndex, UniqueConnec), IoError> { + node_index: NodeIndex + ) -> Option> { let mut connections = self.connections.write(); - let who = accept_connection(&mut connections, &self.next_node_index, - node_id, Endpoint::Listener)?; - let infos = connections.info_by_peer.get_mut(&who) - .expect("Newly-created peer id is always valid"); - let connec = infos.ping_connec.clone(); - Ok((who, connec)) + let infos = match connections.info_by_peer.get_mut(&node_index) { + Some(i) => i, + None => return None + }; + Some(infos.ping_connec.clone()) } /// Cleans up inactive connections and returns a list of - /// connections to ping. - pub fn cleanup_and_prepare_ping( + /// connections to ping and identify. + pub fn cleanup_and_prepare_updates( &self - ) -> Vec<(NodeIndex, PeerId, UniqueConnec)> { + ) -> Vec { + self.topology.write().cleanup(); + let mut connections = self.connections.write(); let connections = &mut *connections; let peer_by_nodeid = &mut connections.peer_by_nodeid; @@ -550,70 +603,46 @@ impl NetworkState { return false; } - ret.push((who, infos.id.clone(), infos.ping_connec.clone())); + if let Some(addr) = infos.remote_addresses.get(0) { + ret.push(PeriodicUpdate { + node_index: who, + peer_id: infos.id.clone(), + address: addr.clone(), + pinger: infos.ping_connec.clone(), + identify: infos.client_version.is_none(), + }); + } true }); ret } - /// Try to add a new connection to a node in the list. - /// - /// Returns a `NodeIndex` to allow further interfacing with this connection. - /// Note that all `NodeIndex`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. + /// Obtains the `UniqueConnec` corresponding to a custom protocol connection to a peer. /// - /// The various methods of the `NetworkState` that close a connection do - /// so by dropping this sender. + /// Returns `None` if the node index is invalid. pub fn custom_proto( &self, - node_id: PeerId, + node_index: NodeIndex, protocol_id: ProtocolId, - endpoint: Endpoint, - ) -> Result<(NodeIndex, UniqueConnec<(mpsc::UnboundedSender, u8)>), IoError> { + ) -> Option, u8)>> { let mut connections = self.connections.write(); - - if is_peer_disabled(&self.disabled_nodes, &node_id) { - debug!(target: "sub-libp2p", "Refusing node {:?} because it was disabled", node_id); - return Err(IoError::new(IoErrorKind::PermissionDenied, "disabled peer")) - } - - let who = accept_connection(&mut connections, &self.next_node_index, - node_id.clone(), endpoint)?; - - let num_open_connections = num_open_custom_connections(&connections, &self.reserved_peers.read()); - - let infos = connections.info_by_peer.get_mut(&who) - .expect("Newly-created peer id is always valid"); - - let node_is_reserved = self.reserved_peers.read().contains(&infos.id); - if !node_is_reserved { - if self.reserved_only.load(atomic::Ordering::Relaxed) || - (endpoint == Endpoint::Listener && - num_open_connections.unreserved_incoming >= self.max_incoming_peers) || - (endpoint == Endpoint::Dialer && - num_open_connections.unreserved_outgoing >= self.max_outgoing_peers) - { - 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 infos = match connections.info_by_peer.get_mut(&node_index) { + Some(i) => i, + None => return None + }; if let Some((_, ref uconn)) = infos.protocols.iter().find(|&(prot, _)| prot == &protocol_id) { - return Ok((who, uconn.clone())) + return Some(uconn.clone()) } let unique_connec = UniqueConnec::empty(); infos.protocols.push((protocol_id.clone(), unique_connec.clone())); - Ok((who, unique_connec)) + Some(unique_connec) } /// Sends some data to the given peer, using the sender that was passed /// to the `UniqueConnec` of `custom_proto`. - pub fn send(&self, protocol: ProtocolId, who: NodeIndex, message: Bytes) -> Result<(), Error> { + pub fn send(&self, who: NodeIndex, protocol: ProtocolId, message: Bytes) -> Result<(), Error> { if let Some(peer) = self.connections.read().info_by_peer.get(&who) { let sender = peer.protocols.iter().find(|elem| elem.0 == protocol) .and_then(|e| e.1.poll()) @@ -660,6 +689,10 @@ impl NetworkState { peer_info.protocols.iter().filter(|c| c.1.is_alive()).count()); let old = connections.peer_by_nodeid.remove(&peer_info.id); debug_assert_eq!(old, Some(who)); + for addr in &peer_info.remote_addresses { + self.topology.write().report_disconnected(addr, + DisconnectReason::ClosedGracefully); // TODO: wrong reason + } } } @@ -682,13 +715,13 @@ impl NetworkState { /// of `custom_proto`). pub fn ban_peer(&self, who: NodeIndex, reason: &str) { // TODO: what do we do if the peer is reserved? - // TODO: same logging as in disconnect_peer + // TODO: same logging as in drop_peer let mut connections = self.connections.write(); let peer_info = if let Some(peer_info) = connections.info_by_peer.remove(&who) { - if let (&Some(ref client_version), &Some(ref remote_address)) = (&peer_info.client_version, &peer_info.remote_address) { - info!(target: "network", "Peer {} (version: {}, address: {}) disabled. {}", who, client_version, remote_address, reason); + if let &Some(ref client_version) = &peer_info.client_version { + info!(target: "network", "Peer {} (version: {}, addresses: {:?}) disabled. {}", who, client_version, peer_info.remote_addresses, reason); } else { - info!(target: "network", "Peer {} disabled. {}", who, reason); + info!(target: "network", "Peer {} (addresses: {:?}) disabled. {}", who, peer_info.remote_addresses, reason); } let old = connections.peer_by_nodeid.remove(&peer_info.id); debug_assert_eq!(old, Some(who)); @@ -707,19 +740,15 @@ impl NetworkState { /// This is done in an atomical way, so that an error doesn't corrupt /// anything. pub fn flush_caches_to_disk(&self) -> Result<(), IoError> { - match self.node_store { - NodeStore::Memory(_) => Ok(()), - NodeStore::Json(ref json) => - match json.flush() { - Ok(()) => { - debug!(target: "sub-libp2p", "Flushed JSON peer store to disk"); - Ok(()) - } - Err(err) => { - warn!(target: "sub-libp2p", "Failed to flush changes to JSON peer store: {}", err); - Err(err) - } - } + match self.topology.read().flush_to_disk() { + Ok(()) => { + debug!(target: "sub-libp2p", "Flushed JSON peer store to disk"); + Ok(()) + } + Err(err) => { + warn!(target: "sub-libp2p", "Failed to flush changes to JSON peer store: {}", err); + Err(err) + } } } } @@ -730,56 +759,18 @@ impl Drop for NetworkState { } } -/// Assigns a `NodeIndex` to a node, or returns an existing ID if any exists. -/// -/// The function only accepts already-locked structs, so that we don't risk -/// any deadlock. -fn accept_connection( - connections: &mut Connections, - next_node_index: &atomic::AtomicUsize, - node_id: PeerId, - endpoint: Endpoint -) -> Result { - let peer_by_nodeid = &mut connections.peer_by_nodeid; - let info_by_peer = &mut connections.info_by_peer; - - let who = *peer_by_nodeid.entry(node_id.clone()).or_insert_with(|| { - let new_id = next_node_index.fetch_add(1, atomic::Ordering::Relaxed); - trace!(target: "sub-libp2p", "Creating new peer #{:?} for {:?}", new_id, node_id); - - info_by_peer.insert(new_id, PeerConnectionInfo { - protocols: Vec::new(), // TODO: Vec::with_capacity(num_registered_protocols), - kad_connec: UniqueConnec::empty(), - ping_connec: UniqueConnec::empty(), - id: node_id.clone(), - originated: endpoint == Endpoint::Dialer, - ping: Mutex::new(None), - client_version: None, - local_address: None, - remote_address: None, - }); - new_id - }); - - Ok(who) -} - -/// Returns true if a peer is disabled. -fn is_peer_disabled( - list: &Mutex>, - peer: &PeerId -) -> bool { - let mut list = list.lock(); - if let Some(timeout) = list.get(peer).cloned() { - if timeout > Instant::now() { - true - } else { - list.remove(peer); - false - } - } else { - false - } +/// Periodic update that should be performed by the user of the network state. +pub struct PeriodicUpdate { + /// Index of the node in the network state. + pub node_index: NodeIndex, + /// Id of the peer. + pub peer_id: PeerId, + /// Address of the node to ping. + pub address: Multiaddr, + /// Object that allows pinging the node. + pub pinger: UniqueConnec, + /// The node should be identified as well. + pub identify: bool, } struct OpenCustomConnectionsNumbers { @@ -814,7 +805,7 @@ fn num_open_custom_connections(connections: &Connections, reserved_peers: &FnvHa total += 1; let node_is_reserved = reserved_peers.contains(&info.id); if !node_is_reserved { - if !info.originated { + if !info.originated.unwrap_or(true) { unreserved_incoming += 1; } else { unreserved_outgoing += 1; @@ -830,32 +821,21 @@ fn num_open_custom_connections(connections: &Connections, reserved_peers: &FnvHa } /// Parses an address of the form `/ip4/x.x.x.x/tcp/x/p2p/xxxxxx`, and adds it -/// to the given node_store. Returns the corresponding peer ID. -fn parse_and_add_to_node_store( +/// to the given topology. Returns the corresponding peer ID and multiaddr. +fn parse_and_add_to_topology( addr_str: &str, - node_store: &NodeStore -) -> Result { + topology: &mut NetTopology +) -> Result<(PeerId, Multiaddr), Error> { let mut addr = addr_str.to_multiaddr().map_err(|_| ErrorKind::AddressParse)?; let who = match addr.pop() { Some(AddrComponent::P2P(key)) => - PeerId::from_bytes(key).map_err(|_| ErrorKind::AddressParse)?, + PeerId::from_multihash(key).map_err(|_| ErrorKind::AddressParse)?, _ => return Err(ErrorKind::AddressParse.into()), }; - // Registering the bootstrap node with a TTL of 100000 years TODO: wrong - match node_store { - NodeStore::Memory(ref node_store) => - node_store - .peer_or_create(&who) - .set_addr_ttl(addr, Duration::from_secs(100000 * 365 * 24 * 3600)), - NodeStore::Json(ref node_store) => - node_store - .peer_or_create(&who) - .set_addr_ttl(addr, Duration::from_secs(100000 * 365 * 24 * 3600)), - } - - Ok(who) + topology.add_bootstrap_addr(&who, addr.clone()); + Ok((who, addr)) } /// Obtains or generates the local private key using the configuration. @@ -969,7 +949,7 @@ fn open_priv_key_file

(path: P) -> Result #[cfg(test)] mod tests { - use libp2p::core::{Endpoint, PublicKey}; + use libp2p::core::PublicKey; use network_state::NetworkState; #[test] @@ -977,18 +957,9 @@ mod tests { let state = NetworkState::new(&Default::default()).unwrap(); let example_peer = PublicKey::Rsa(vec![1, 2, 3, 4]).into_peer_id(); - let (who, _) = state.custom_proto( - example_peer.clone(), - [1, 2, 3], - Endpoint::Dialer - ).unwrap(); - + let who = state.assign_node_index(&example_peer).unwrap(); state.ban_peer(who, "Just a test"); - assert!(state.custom_proto( - example_peer.clone(), - [1, 2, 3], - Endpoint::Dialer - ).is_err()); + assert!(state.assign_node_index(&example_peer).is_err()); } } diff --git a/substrate/network-libp2p/src/service.rs b/substrate/network-libp2p/src/service.rs index d5cf8bc0f135d..a612bc7449e13 100644 --- a/substrate/network-libp2p/src/service.rs +++ b/substrate/network-libp2p/src/service.rs @@ -23,8 +23,8 @@ use libp2p::multiaddr::{AddrComponent, Multiaddr}; use libp2p::kad::{KadSystem, KadConnecConfig, KadSystemConfig}; use libp2p::kad::{KadIncomingRequest, KadConnecController, KadPeer}; use libp2p::kad::{KadConnectionType, KadQueryEvent}; -use libp2p::identify::{IdentifyInfo, IdentifyOutput, IdentifyTransportOutcome}; -use libp2p::identify::{IdentifyProtocolConfig, PeerIdTransport}; +use libp2p::identify::{IdentifyInfo, IdentifyOutput, IdentifySender}; +use libp2p::identify::{IdentifyProtocolConfig}; use libp2p::core::{upgrade, Transport, MuxedTransport, ConnectionUpgrade}; use libp2p::core::{Endpoint, PeerId as PeerstorePeerId, PublicKey}; use libp2p::core::{SwarmController, UniqueConnecState}; @@ -38,7 +38,7 @@ use std::sync::Arc; use std::sync::mpsc as sync_mpsc; use std::thread; use std::time::{Duration, Instant}; -use futures::{future, Future, Stream, IntoFuture}; +use futures::{future, Future, stream, Stream}; use futures::sync::{mpsc, oneshot}; use tokio::runtime::current_thread; use tokio_io::{AsyncRead, AsyncWrite}; @@ -46,7 +46,7 @@ use tokio_timer::{Interval, Deadline}; use custom_proto::{RegisteredProtocol, RegisteredProtocols}; use custom_proto::RegisteredProtocolOutput; -use network_state::NetworkState; +use network_state::{NetworkState, PeriodicUpdate}; use timeouts; use transport; @@ -90,7 +90,7 @@ struct Shared { /// Original address from the configuration, after being adjusted by the `Transport`. // TODO: because we create the `Shared` before starting to listen, this // has to be set later ; sort this out - original_listened_addr: RwLock>, + original_listened_addr: RwLock>, /// Contains the addresses we known about ourselves. listened_addrs: RwLock>, @@ -110,7 +110,7 @@ impl NetworkService { let local_peer_id = network_state.local_public_key().clone() .into_peer_id(); for mut addr in config.listen_addresses.iter().cloned() { - addr.append(AddrComponent::P2P(local_peer_id.clone().into_bytes())); + addr.append(AddrComponent::P2P(local_peer_id.clone().into())); info!(target: "sub-libp2p", "Local node address is: {}", addr); } @@ -119,7 +119,7 @@ impl NetworkService { local_peer_id: local_peer_id.clone(), kbuckets_timeout: Duration::from_secs(600), request_timeout: Duration::from_secs(10), - known_initial_peers: network_state.known_peers(), + known_initial_peers: network_state.known_peers().into_iter(), }); // Channel we use to signal success or failure of the bg thread @@ -143,7 +143,7 @@ impl NetworkService { kad_upgrade: KadConnecConfig::new(), config, timeouts_register_tx, - original_listened_addr: RwLock::new(None), + original_listened_addr: RwLock::new(Vec::new()), listened_addrs: RwLock::new(listened_addrs), }); @@ -204,7 +204,7 @@ impl NetworkService { // 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 - self.shared.original_listened_addr.read().as_ref() + self.shared.original_listened_addr.read().get(0) .map(|addr| format!("{}/p2p/{}", addr, self.shared.kad_system.local_peer_id().to_base58()) ) @@ -292,7 +292,7 @@ impl NetworkContext for NetworkContextImpl { let mut message = Bytes::with_capacity(1 + data.len()); message.extend_from_slice(&[packet_id]); message.extend_from_slice(&data); - if self.inner.network_state.send(protocol, peer, message).is_err() { + if self.inner.network_state.send(peer, protocol, message).is_err() { debug!(target: "sub-libp2p", "Sending to peer {} failed. Dropping.", peer); self.inner.network_state.drop_peer(peer); } @@ -308,11 +308,11 @@ impl NetworkContext for NetworkContextImpl { fn report_peer(&self, peer: NodeIndex, reason: Severity) { if let Some(info) = self.inner.network_state.peer_info(peer) { - if let (Some(client_version), Some(remote_address)) = (info.client_version, info.remote_address) { + if let Some(client_version) = info.client_version { info!(target: "sub-libp2p", - "Peer {} ({} {}) reported by client: {}", + "Peer {} ({:?} {}) reported by client: {}", peer, - remote_address, + info.remote_address, client_version, reason ); @@ -382,39 +382,39 @@ fn init_thread( // Build the transport layer. let transport = { let base = transport::build_transport( - transport::UnencryptedAllowed::Denied, shared.network_state.local_private_key().clone() ); - let addr_resolver = { + let base = base.map_err_dial({ let shared = shared.clone(); - move |who| { - let addrs = shared.network_state.addrs_of_peer(&who); - for addr in &addrs { - trace!(target: "sub-libp2p", "{:?} resolved as {}", who, addr); - } - addrs.into_iter() + move |err, addr| { + trace!(target: "sub-libp2p", "Failed to dial {}: {:?}", addr, err); + shared.network_state.report_failed_to_connect(&addr); + err } - }; + }); - PeerIdTransport::new(base.clone(), addr_resolver).and_then({ - let shared = shared.clone(); - move |out, endpoint, remote_addr| { - let original_addr = out.original_addr.clone(); - let info = out.info.and_then(move |info| { - process_identify_info(shared, &info, original_addr, - endpoint, &base)?; - Ok(info) - }); + let shared = shared.clone(); + base.and_then(move |(peer_id, stream), endpoint, remote_addr| { + remote_addr.and_then(move |remote_addr| { + if &peer_id == shared.kad_system.local_peer_id() { + // TODO: this happens very frequently for now and floods the logs + //warn!(target: "sub-libp2p", "Refusing connection from our local peer id"); + return Err(IoErrorKind::ConnectionRefused.into()) + } + // TODO: there's a possible race condition here if `cleanup_and_prepare_updates` is + // called between `assign_node_index` and one of `kad_connec`, `unique_connec`, + // etc. ; in practice though, it is very unlikely to happen + let node_index = shared.network_state.assign_node_index(&peer_id)?; + shared.network_state.report_connected(node_index, &remote_addr, endpoint)?; let out = TransportOutput { - socket: out.socket, - info: Box::new(info) as Box<_>, - original_addr: out.original_addr, + socket: stream, + node_index, + original_addr: remote_addr.clone(), }; - - future::ok((out, remote_addr)) - } + Ok((out, future::ok(remote_addr))) + }) }) }; @@ -425,12 +425,13 @@ fn init_thread( .and_then({ let shared = shared.clone(); move |out, endpoint, client_addr| { + let node_index = out.node_index; let original_addr = out.original_addr; let listener_upgrade = upgrade::or(upgrade::or(upgrade::or( - upgrade::map_with_addr(shared.kad_upgrade.clone(), |(c, f), a| FinalUpgrade::Kad(c, f, a.clone())), - upgrade::map(IdentifyProtocolConfig, |id| FinalUpgrade::Identify(id, original_addr))), - upgrade::map_with_addr(ping::Ping, |out, addr| FinalUpgrade::from((out, addr.clone())))), - upgrade::map_with_addr(DelayedProtosList(shared), |c, a| FinalUpgrade::Custom(c, a.clone()))); + upgrade::map(shared.kad_upgrade.clone(), move |(c, f)| FinalUpgrade::Kad(node_index, c, f)), + upgrade::map(IdentifyProtocolConfig, move |id| FinalUpgrade::from((node_index, id, original_addr)))), + upgrade::map(ping::Ping, move |out| FinalUpgrade::from((node_index, out)))), + upgrade::map(DelayedProtosList(shared), move |c| FinalUpgrade::Custom(node_index, c))); upgrade::apply(out.socket, listener_upgrade, endpoint, client_addr) } }); @@ -448,7 +449,7 @@ fn init_thread( match swarm_controller.listen_on(addr.clone()) { Ok(new_addr) => { debug!(target: "sub-libp2p", "Libp2p listening on {}", new_addr); - *shared.original_listened_addr.write() = Some(new_addr.clone()); + shared.original_listened_addr.write().push(new_addr.clone()); }, Err(_) => { warn!(target: "sub-libp2p", "Can't listen on {}, protocol not supported", addr); @@ -459,15 +460,16 @@ fn init_thread( // Explicitely connect to _all_ the boostrap nodes as a temporary measure. for bootnode in shared.config.boot_nodes.iter() { - match shared.network_state.add_peer(bootnode) { - Ok(who) => { - trace!(target: "sub-libp2p", "Dialing bootnode {:?}", who); + match shared.network_state.add_bootstrap_peer(bootnode) { + Ok((who, addr)) => { + trace!(target: "sub-libp2p", "Dialing bootnode {:?} through {}", who, addr); for proto in shared.protocols.0.clone().into_iter() { open_peer_custom_proto( shared.clone(), transport.clone(), + addr.clone(), + Some(who.clone()), proto, - who.clone(), &swarm_controller ) } @@ -488,11 +490,12 @@ fn init_thread( if let Ok(addr) = multi { trace!(target: "sub-libp2p", "Missing NodeIndex for Bootnode {:}. Querying", bootnode); for proto in shared.protocols.0.clone().into_iter() { - connect_with_query_peer_id( + open_peer_custom_proto( shared.clone(), transport.clone(), - proto, addr.clone(), + None, + proto, &swarm_controller ) } @@ -505,18 +508,17 @@ fn init_thread( } } - shared.network_state.set_non_reserved_mode(shared.config.non_reserved_mode.clone()); - for reserved in shared.config.reserved_nodes.iter() { - match shared.network_state.add_reserved_peer(reserved) { - Ok(who) => { - trace!(target: "sub-libp2p", "Added reseved peer {:?}", who); - }, - Err(err) => warn!(target:"sub-libp2p", "Couldn't parse reserved address: {}", err), - } - } - - // Start connecting to nodes now. - connect_to_nodes(shared.clone(), transport.clone(), &swarm_controller); + let outgoing_connections = Interval::new(Instant::now(), Duration::from_secs(5)) + .map_err(|err| IoError::new(IoErrorKind::Other, err)) + .for_each({ + let shared = shared.clone(); + let transport = transport.clone(); + let swarm_controller = swarm_controller.clone(); + move |_| { + connect_to_nodes(shared.clone(), transport.clone(), &swarm_controller); + Ok(()) + } + }); // Build the timeouts system for the `register_timeout` function. // (note: this has nothing to do with socket timeouts) @@ -542,12 +544,13 @@ fn init_thread( transport.clone(), swarm_controller.clone()); // Start the process of pinging the active nodes on the network. - let pinger = start_pinger(shared.clone(), transport, swarm_controller); + let periodic = start_periodic_updates(shared.clone(), transport, swarm_controller); // Merge all the futures into one! Ok(swarm_future .select(discovery).map_err(|(err, _)| err).and_then(|(_, rest)| rest) - .select(pinger).map_err(|(err, _)| err).and_then(|(_, rest)| rest) + .select(periodic).map_err(|(err, _)| err).and_then(|(_, rest)| rest) + .select(outgoing_connections).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) @@ -561,28 +564,42 @@ fn init_thread( /// Output of the common transport layer. struct TransportOutput { socket: S, - info: Box>, + node_index: NodeIndex, original_addr: Multiaddr, } /// Enum of all the possible protocols our service handles. enum FinalUpgrade { - Kad(KadConnecController, Box>, Multiaddr), + Kad(NodeIndex, KadConnecController, Box>), /// The remote identification system, and the multiaddress we see the remote as. - Identify(IdentifyOutput, Multiaddr), - PingDialer(ping::Pinger, Box>, Multiaddr), - PingListener(Box>, Multiaddr), + IdentifyListener(NodeIndex, IdentifySender, Multiaddr), + /// The remote information about the address they see us as. + IdentifyDialer(NodeIndex, IdentifyInfo, Multiaddr), + PingDialer(NodeIndex, ping::Pinger, Box>), + PingListener(NodeIndex, Box>), /// `Custom` means anything not in the core libp2p and is handled /// by `CustomProtoConnectionUpgrade`. - Custom(RegisteredProtocolOutput>, Multiaddr), + Custom(NodeIndex, RegisteredProtocolOutput>), } -impl From<(ping::PingOutput, Multiaddr)> for FinalUpgrade { - fn from((out, addr): (ping::PingOutput, Multiaddr)) -> FinalUpgrade { +impl From<(NodeIndex, ping::PingOutput)> for FinalUpgrade { + fn from((node_index, out): (NodeIndex, ping::PingOutput)) -> FinalUpgrade { match out { - ping::PingOutput::Ponger(processing) => FinalUpgrade::PingListener(processing, addr), + ping::PingOutput::Ponger(processing) => + FinalUpgrade::PingListener(node_index, processing), ping::PingOutput::Pinger { pinger, processing } => - FinalUpgrade::PingDialer(pinger, processing, addr), + FinalUpgrade::PingDialer(node_index, pinger, processing), + } + } +} + +impl From<(NodeIndex, IdentifyOutput, Multiaddr)> for FinalUpgrade { + fn from((node_index, out, addr): (NodeIndex, IdentifyOutput, Multiaddr)) -> FinalUpgrade { + match out { + IdentifyOutput::RemoteInfo { info, observed_addr } => + FinalUpgrade::IdentifyDialer(node_index, info, observed_addr), + IdentifyOutput::Sender { sender } => + FinalUpgrade::IdentifyListener(node_index, sender, addr), } } } @@ -594,16 +611,16 @@ fn listener_handle<'a, C>( ) -> Box + 'a> where C: AsyncRead + AsyncWrite + 'a { match upgrade { - FinalUpgrade::Kad(controller, kademlia_stream, client_addr) => { - trace!(target: "sub-libp2p", "Opened kademlia substream with {:?}", client_addr); - match handle_kademlia_connection(shared, client_addr, controller, kademlia_stream) { + FinalUpgrade::Kad(node_index, controller, kademlia_stream) => { + trace!(target: "sub-libp2p", "Opened kademlia substream with #{:?}", node_index); + match handle_kademlia_connection(shared, node_index, controller, kademlia_stream) { Ok(fut) => Box::new(fut) as Box<_>, Err(err) => Box::new(future::err(err)) as Box<_>, } }, - FinalUpgrade::Identify(IdentifyOutput::Sender { sender }, original_addr) => { - trace!(target: "sub-libp2p", "Sending back identification info"); + FinalUpgrade::IdentifyListener(node_index, sender, original_addr) => { + trace!(target: "sub-libp2p", "Sending back identification info to #{}", node_index); sender.send( IdentifyInfo { public_key: shared.network_state.local_public_key().clone(), @@ -618,30 +635,30 @@ fn listener_handle<'a, C>( ) }, - FinalUpgrade::Identify(IdentifyOutput::RemoteInfo { .. }, _) => - unreachable!("We are never dialing with the identify protocol"), + FinalUpgrade::IdentifyDialer(node_index, info, observed_addr) => { + process_identify_info(&shared, node_index, &info, &observed_addr); + Box::new(future::ok(())) + }, - FinalUpgrade::PingListener(future, client_addr) => { - trace!(target: "sub-libp2p", "Received ping substream from {:?}", client_addr); + FinalUpgrade::PingListener(node_index, future) => { + trace!(target: "sub-libp2p", "Received ping substream from #{}", node_index); future }, - FinalUpgrade::PingDialer(pinger, future, client_addr) => { - let node_id = p2p_multiaddr_to_node_id(client_addr); - match shared.network_state.ping_connection(node_id.clone()) { - Ok((_, ping_connec)) => { - trace!(target: "sub-libp2p", "Successfully opened ping substream with {:?}", node_id); - let fut = ping_connec.tie_or_passthrough(pinger, future); - Box::new(fut) as Box<_> - }, - Err(err) => Box::new(future::err(err)) as Box<_> - } + FinalUpgrade::PingDialer(node_index, pinger, future) => { + let ping_connec = match shared.network_state.ping_connection(node_index) { + Some(p) => p, + None => return Box::new(future::ok(())) as Box<_> + }; + trace!(target: "sub-libp2p", "Successfully opened ping substream with #{}", node_index); + let fut = ping_connec.tie_or_passthrough(pinger, future); + Box::new(fut) as Box<_> }, - FinalUpgrade::Custom(custom_proto_out, client_addr) => { + FinalUpgrade::Custom(node_index, custom_proto_out) => { // A "custom" protocol is one that is part of substrate and not part of libp2p. let shared = shared.clone(); - let fut = handle_custom_connection(shared, client_addr, custom_proto_out); + let fut = handle_custom_connection(shared, node_index, custom_proto_out); Box::new(fut) as Box<_> }, } @@ -650,14 +667,20 @@ fn listener_handle<'a, C>( /// Handles a newly-opened Kademlia connection. fn handle_kademlia_connection( shared: Arc, - client_addr: Multiaddr, + node_index: NodeIndex, controller: KadConnecController, kademlia_stream: Box> ) -> Result, IoError> { - let node_id = p2p_multiaddr_to_node_id(client_addr); - let (who, kad_connec) = shared.network_state - .kad_connection(node_id.clone())?; - + let kad_connec = match shared.network_state.kad_connection(node_index) { + Some(kad) => kad, + None => return Err(IoError::new(IoErrorKind::Other, "node no longer exists")), + }; + + let node_id = match shared.network_state.node_id_from_index(node_index) { + Some(id) => id, + None => return Err(IoError::new(IoErrorKind::Other, "node no longer exists")), + }; + let node_id2 = node_id.clone(); let future = future::loop_fn(kademlia_stream, move |kademlia_stream| { let shared = shared.clone(); @@ -684,7 +707,7 @@ fn handle_kademlia_connection( Ok(future::Loop::Continue(rest)) }) }).then(move |val| { - trace!(target: "sub-libp2p", "Closed Kademlia connection with #{} {:?} => {:?}", who, node_id2, val); + trace!(target: "sub-libp2p", "Closed Kademlia connection with #{} {:?} => {:?}", node_index, node_id2, val); val }); @@ -738,34 +761,29 @@ fn build_kademlia_response( /// Returns a future that corresponds to when the handling is finished. fn handle_custom_connection( shared: Arc, - client_addr: Multiaddr, + node_index: NodeIndex, custom_proto_out: RegisteredProtocolOutput> ) -> impl Future { 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 = p2p_multiaddr_to_node_id(client_addr); - // 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 (who, unique_connec) = match shared.network_state.custom_proto( - node_id.clone(), + let unique_connec = match shared.network_state.custom_proto( + node_index, protocol_id, - custom_proto_out.endpoint, ) { - Ok(a) => a, - Err(err) => return future::Either::A(future::err(err.into())), + Some(c) => c, + None => return future::Either::A(future::err(IoErrorKind::Other.into())), }; if let UniqueConnecState::Full = unique_connec.state() { debug!(target: "sub-libp2p", - "Interrupting connection attempt to {:?} with {:?} because we're already connected", - node_id, + "Interrupting connection attempt to #{} with {:?} because we're already connected", + node_index, custom_proto_out.protocol_id ); return future::Either::A(future::ok(())) @@ -774,7 +792,6 @@ fn handle_custom_connection( struct ProtoDisconnectGuard { inner: Arc, who: NodeIndex, - node_id: PeerstorePeerId, handler: Arc, protocol: ProtocolId, print_log_message: bool, @@ -785,7 +802,7 @@ fn handle_custom_connection( if self.print_log_message { info!(target: "sub-libp2p", "Node {:?} with peer ID {} through protocol {:?} disconnected", - self.node_id, + self.inner.network_state.node_id_from_index(self.who), self.who, self.protocol ); @@ -804,8 +821,7 @@ fn handle_custom_connection( let mut dc_guard = ProtoDisconnectGuard { inner: shared.clone(), - who, - node_id: node_id.clone(), + who: node_index, handler: handler.clone(), protocol: protocol_id, print_log_message: true, @@ -815,36 +831,34 @@ fn handle_custom_connection( .for_each({ let shared = shared.clone(); let handler = handler.clone(); - let node_id = node_id.clone(); move |(packet_id, data)| { - shared.kad_system.update_kbuckets(node_id.clone()); + if let Some(id) = shared.network_state.node_id_from_index(node_index) { + shared.kad_system.update_kbuckets(id); + } handler.read(&NetworkContextImpl { inner: shared.clone(), protocol: protocol_id, - current_peer: Some(who.clone()), - }, &who, packet_id, &data); + current_peer: Some(node_index.clone()), + }, &node_index, packet_id, &data); Ok(()) } }); let val = (custom_proto_out.outgoing, custom_proto_out.protocol_version); let final_fut = unique_connec.tie_or_stop(val, fut) - .then({ - let node_id = node_id.clone(); - move |val| { - info!(target: "sub-libp2p", "Finishing future for proto {:?} with {:?} => {:?}", - protocol_id, node_id, val); - // Makes sure that `dc_guard` is kept alive until here. - dc_guard.print_log_message = false; - drop(dc_guard); - val - } + .then(move |val| { + info!(target: "sub-libp2p", "Finishing future for proto {:?} with {:?} => {:?}", + protocol_id, node_index, val); + // Makes sure that `dc_guard` is kept alive until here. + dc_guard.print_log_message = false; + drop(dc_guard); + val }); debug!(target: "sub-libp2p", - "Successfully connected to {:?} (peer id {}) with protocol {:?} version {}", - node_id, - who, + "Successfully connected to {:?} (peer id #{}) with protocol {:?} version {}", + shared.network_state.node_id_from_index(node_index), + node_index, protocol_id, custom_proto_out.protocol_version ); @@ -852,8 +866,8 @@ fn handle_custom_connection( handler.connected(&NetworkContextImpl { inner: shared.clone(), protocol: protocol_id, - current_peer: Some(who), - }, &who); + current_peer: Some(node_index), + }, &node_index); future::Either::B(final_fut) } @@ -862,9 +876,12 @@ fn handle_custom_connection( /// 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, - swarm_controller: SwarmController) -> impl Future - where T: MuxedTransport> + Clone + 'static, +fn start_kademlia_discovery( + shared: Arc, + transport: T, + swarm_controller: SwarmController +) -> impl Future + where T: MuxedTransport> + Clone + 'static, T::MultiaddrFuture: 'static, To: AsyncRead + AsyncWrite + 'static, St: MuxedTransport> + Clone + 'static, @@ -882,35 +899,17 @@ fn start_kademlia_discovery(shared: Arc, transport: T, ) }); + // We perform a random Kademlia query at a regular interval. let discovery = Interval::new(Instant::now(), Duration::from_secs(32)) - // TODO: add a timeout to the lookups + // TODO: add a timeout to the lookups? .map_err(|err| IoError::new(IoErrorKind::Other, err)) - .and_then({ + .for_each({ let shared = shared.clone(); let transport = transport.clone(); let swarm_controller = swarm_controller.clone(); move |_| { - // Note that this is a small hack. We flush the caches here so - // that we don't need to run a timer just for flushing. let _ = shared.network_state.flush_caches_to_disk(); - - if shared.network_state.should_open_outgoing_custom_connections() != 0 { - future::Either::A(perform_kademlia_query(shared.clone(), - transport.clone(), swarm_controller.clone())) - } else { - // If we shouldn't open connections (eg. 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(())) - } - } - }) - .for_each({ - let shared = shared.clone(); - move |_| { - connect_to_nodes(shared.clone(), transport.clone(), &swarm_controller); - Ok(()) + perform_kademlia_query(shared.clone(), transport.clone(), swarm_controller.clone()) } }); @@ -985,23 +984,9 @@ fn connect_to_nodes( To: AsyncRead + AsyncWrite + 'static, St: MuxedTransport> + Clone + 'static, C: 'static { - let num_slots = shared.network_state.should_open_outgoing_custom_connections(); - debug!(target: "sub-libp2p", - "Outgoing connections cycle ; opening up to {} outgoing connections", - num_slots - ); - - for _ in 0 .. num_slots { - // Choose a random peer. We are potentially already connected to - // this peer, but this is not a problem as this function is called - // regularly. - // TODO: is it ^ ? - let peer = match shared.network_state.random_peer() { - Some(p) => p, - // `None` returned when no peer is known - None => break, - }; + let (addrs, _will_change) = shared.network_state.outgoing_connections_to_attempt(); + for (peer, addr) in addrs.into_iter() { // 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. @@ -1009,20 +994,29 @@ fn connect_to_nodes( open_peer_custom_proto( shared.clone(), base_transport.clone(), + addr.clone(), + Some(peer.clone()), proto, - peer.clone(), swarm_controller ) } } } - -fn connect_with_query_peer_id( +/// Dials the given address for the given protocol and using the given `swarm_controller`. +/// +/// This function *always* performs a dial, and doesn't check whether we already have an existing +/// connection to the remote. This is expected to be checked by the caller. +/// +/// The dialing will fail if the obtained peer ID doesn't match the expected ID. This is an +/// opinionated decision, as we could just let the new connection through. But we decide not to. +/// If `None` is passed for the expected peer ID, we always accept the connection. +fn open_peer_custom_proto( shared: Arc, base_transport: T, - proto: RegisteredProtocol>, addr: Multiaddr, + expected_peer_id: Option, + proto: RegisteredProtocol>, swarm_controller: &SwarmController ) where T: MuxedTransport> + Clone + 'static, @@ -1031,227 +1025,145 @@ fn connect_with_query_peer_id( St: MuxedTransport> + Clone + 'static, C: 'static, { - let addr2 = addr.clone(); + let proto_id = proto.id(); + let with_proto = base_transport - .clone() .and_then(move |out, endpoint, client_addr| { - trace!(target: "sub-libp2p", "in"); - let socket = out.socket; - let original_addr = out.original_addr; - out.info - .and_then(move |info| { - let _ = process_identify_info(shared, &info, original_addr, - endpoint, &base_transport); - trace!(target: "sub-libp2p", - "Bootnode {:} found with peer id: {:?}", - addr2, - info.info.public_key.into_peer_id() - ); - upgrade::apply(socket, proto, endpoint, client_addr) - }) - }) - .and_then(move |out, _endpoint, client_addr| - client_addr.map(move |client_addr| - (FinalUpgrade::Custom(out, client_addr.clone()), future::ok(client_addr)) - ) - ); - - let with_timeout = TransportTimeout::new(with_proto, Duration::from_secs(10)); - let with_err = with_timeout - .map_err({ - let addr = addr.clone(); - move |err| { - warn!(target: "sub-libp2p", - "Error while dialing {:?} to query peer id: {:?}", - addr, - err - ); - err - } + let node_index = out.node_index; + upgrade::apply(out.socket, proto, endpoint, client_addr) + .map(move |(custom, client_addr)| + ((node_index, FinalUpgrade::Custom(node_index, custom)), client_addr)) }); - let _ = swarm_controller.dial(addr.clone(), with_err) - .map_err(move |err| - warn!(target: "sub-libp2p", "Error when querying peer node info {:} of {:}", err, addr) - ); -} + let with_timeout = TransportTimeout::new(with_proto, Duration::from_secs(20)); -/// If necessary, dials the given address for the given protocol and using the -/// given `swarm_controller`. Has no effect if we already dialed earlier. -/// Checks that the peer ID matches `expected_peer_id`. -// TODO: check that the secio key matches the id given by kademlia -fn open_peer_custom_proto( - shared: Arc, - base_transport: T, - proto: RegisteredProtocol>, - expected_peer_id: PeerstorePeerId, - swarm_controller: &SwarmController -) - where T: MuxedTransport> + Clone + 'static, - T::MultiaddrFuture: 'static, - To: AsyncRead + AsyncWrite + 'static, - St: MuxedTransport> + Clone + 'static, - C: 'static, -{ - // Don't connect to ourselves. - // TODO: remove this eventually - if &expected_peer_id == shared.kad_system.local_peer_id() { - trace!(target: "sub-libp2p", "Skipped connecting to {:?} because it is ourselves", expected_peer_id); - return - } + if let Some(expected_peer_id) = expected_peer_id { + let expected_node_index = match shared.network_state.assign_node_index(&expected_peer_id) { + Ok(i) => i, + Err(_) => return, + }; - let proto_id = proto.id(); - let node_id = expected_peer_id.clone(); - let shared2 = shared.clone(); - let addr: Multiaddr = AddrComponent::P2P(expected_peer_id.clone().into_bytes()).into(); + let unique_connec = match shared.network_state.custom_proto(expected_node_index, proto_id) { + Some(uc) => uc, + None => return, + }; - // TODO: check that the secio key matches the id given by kademlia - let with_proto = base_transport - .clone() - .and_then(move |out, endpoint, client_addr| { - let socket = out.socket; - let original_addr = out.original_addr; - out.info - .and_then(move |info| { - let actual_peer_id = info.info.public_key.into_peer_id(); - if actual_peer_id == expected_peer_id { - Ok(socket) - } else { - debug!(target: "sub-libp2p", - "Public key mismatch for node {:?} ; actual: {:?}", - expected_peer_id, - actual_peer_id - ); - trace!(target: "sub-libp2p", "Removing addr {} for {:?}", original_addr, expected_peer_id); - shared.network_state.set_invalid_kad_address(&expected_peer_id, &original_addr); - Err(IoError::new(IoErrorKind::InvalidData, "public key mismatch when identifying peer")) - } - }) - .and_then(move |socket| - upgrade::apply(socket, proto, endpoint, client_addr) - ) - }) - .and_then(move |out, _endpoint, client_addr| - client_addr.map(move |client_addr| { - let out = FinalUpgrade::Custom(out, client_addr.clone()); - (out, future::ok(client_addr)) - }) + let with_peer_check = with_timeout + .and_then(move |(node_index, custom), _, client_addr| { + if node_index == expected_node_index { + future::ok((custom, client_addr)) + } else { + future::err(IoError::new(IoErrorKind::ConnectionRefused, "Peer id mismatch")) + } + }); + + trace!(target: "sub-libp2p", + "Opening connection to {:?} through {} with proto {:?}", + expected_peer_id, + addr, + proto_id ); - - let with_timeout = TransportTimeout::new(with_proto, - Duration::from_secs(20)); - let with_err = with_timeout - .map_err({ - let node_id = node_id.clone(); - move |err| { - debug!(target: "sub-libp2p", "Error while dialing {:?} with custom proto: {:?}", node_id, err); - err - } - }); - match shared2.network_state.custom_proto(node_id.clone(), proto_id, Endpoint::Dialer) { - Ok((who, unique_connec)) => { - if !unique_connec.is_alive() { - trace!(target: "sub-libp2p", - "Opening connection to #{} {:?} with proto {:?}", - who, - node_id, - proto_id - ); - } + unique_connec.dial(swarm_controller, &addr, with_peer_check); - unique_connec.dial(&swarm_controller, &addr, with_err); - }, - Err(err) => { - trace!(target: "sub-libp2p", - "Error while opening connection to {:?} with proto {:?} => {:?}", - node_id, - proto_id, - err - ); - }, + } else { + let trans = with_timeout.map(|(_, out), _| out); + if let Err(addr) = swarm_controller.dial(addr, trans) { + debug!(target: "sub-libp2p", "Failed to dial {:?}", addr); + } } } /// Obtain a Kademlia connection to the given peer. -fn obtain_kad_connection(shared: Arc, - who: PeerstorePeerId, transport: T, swarm_controller: SwarmController) - -> impl Future - where T: MuxedTransport> + Clone + 'static, +fn obtain_kad_connection( + shared: Arc, + who: PeerstorePeerId, + transport: T, + swarm_controller: SwarmController +) -> impl Future + where T: MuxedTransport> + Clone + 'static, T::MultiaddrFuture: 'static, To: AsyncRead + AsyncWrite + 'static, St: MuxedTransport> + Clone + 'static, C: 'static { let kad_upgrade = shared.kad_upgrade.clone(); - let addr: Multiaddr = AddrComponent::P2P(who.clone().into_bytes()).into(); let transport = transport - .and_then(move |out, endpoint, client_addr| - upgrade::apply(out.socket, kad_upgrade.clone(), - endpoint, client_addr) - ) - .and_then(move |(ctrl, fut), _, client_addr| { - client_addr.map(|client_addr| { - let out = FinalUpgrade::Kad(ctrl, fut, client_addr.clone()); - (out, future::ok(client_addr)) - }) + .and_then(move |out, endpoint, client_addr| { + let node_index = out.node_index; + upgrade::apply(out.socket, kad_upgrade.clone(), endpoint, client_addr) + .map(move |((ctrl, fut), addr)| (FinalUpgrade::Kad(node_index, ctrl, fut), addr)) }); - - let future = shared.network_state - .kad_connection(who.clone()) + + // This function consists in trying all the addresses we know one by one until we find + // one that works. + // + // This `future` returns a Kad controller, or an error if all dialing attempts failed. + let future = stream::iter_ok(shared.network_state.addrs_of_peer(&who)) + .and_then(move |addr| { + let node_index = shared.network_state.assign_node_index(&who)?; + let kad = match shared.network_state.kad_connection(node_index) { + Some(kad) => kad, + None => return Err(IoError::new(IoErrorKind::Other, "node no longer exists")), + }; + Ok((kad, addr)) + }) + .and_then(move |(unique_connec, addr)| { + unique_connec.dial(&swarm_controller, &addr, transport.clone()) + }) + .then(|result| -> Result<_, ()> { Ok(result.ok()) }) + .filter_map(|result| result) .into_future() - .map(move |(_, k)| k.dial(&swarm_controller, &addr, transport)) - .flatten(); + .map_err(|_| -> IoError { unreachable!("all items always succeed") }) + .and_then(|(kad, _)| kad.ok_or_else(|| IoErrorKind::ConnectionRefused.into())); // Note that we use a Box in order to speed up compilation. Box::new(future) as Box> } -/// Processes the information about a node. -/// -/// - `original_addr` is the address used to originally dial this node. -/// - `endpoint` is whether we dialed or listened to this node. -/// - `transport` is used for the `nat_traversal` method. -/// -/// Returns an error if the node has been refused access. +/// Processes the identification information that we received about a node. fn process_identify_info( - shared: Arc, - info: &IdentifyTransportOutcome, - original_addr: Multiaddr, - endpoint: Endpoint, - transport: &impl Transport -) -> Result<(), IoError> { - let node_id = info.info.public_key.clone().into_peer_id(); - let _peer_id = shared.network_state.set_peer_info(node_id.clone(), endpoint, - info.info.agent_version.clone(), original_addr.clone(), - original_addr.clone())?; // TODO: wrong local addr - - if let Some(ref original_listened_addr) = *shared.original_listened_addr.read() { - if let Some(mut ext_addr) = transport.nat_traversal(original_listened_addr, &info.observed_addr) { + shared: &Shared, + node_index: NodeIndex, + info: &IdentifyInfo, + observed_addr: &Multiaddr, +) { + trace!(target: "sub-libp2p", "Received identification info from #{}", node_index); + + shared.network_state.set_node_info(node_index, info.agent_version.clone()); + + for original_listened_addr in &*shared.original_listened_addr.read() { + // TODO: we're using a hack here ; ideally we would call `nat_traversal` on our + // `Transport` ; but that's complicated to pass around ; we could put it in a `Box` in + // `Shared`, but since our transport doesn't implement `Send` (libp2p doesn't implement + // `Send` on modifiers), we can't. Instead let's just recreate a transport locally every + // time. + let transport = libp2p::tcp::TcpConfig::new(); + if let Some(mut ext_addr) = transport.nat_traversal(original_listened_addr, &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, + observed_addr, ext_addr ); listened_addrs.push(ext_addr.clone()); ext_addr.append(AddrComponent::P2P(shared.kad_system - .local_peer_id().clone().into_bytes())); + .local_peer_id().clone().into())); info!(target: "sub-libp2p", "New external node address: {}", ext_addr); } } } - for addr in info.info.listen_addrs.iter() { - shared.network_state.add_kad_discovered_addr(&node_id, addr.clone()); + for addr in info.listen_addrs.iter() { + if let Some(node_id) = shared.network_state.node_id_from_index(node_index) { + shared.network_state.add_kad_discovered_addr(&node_id, addr.clone()); + } } - - Ok(()) } /// Returns a future that regularly pings every peer we're connected to. /// If a peer doesn't respond after a while, we disconnect it. -fn start_pinger( +fn start_periodic_updates( shared: Arc, transport: T, swarm_controller: SwarmController @@ -1261,23 +1173,37 @@ fn start_pinger( To: AsyncRead + AsyncWrite + 'static, St: MuxedTransport> + Clone + 'static, C: 'static { - let transport = transport - .and_then(move |out, endpoint, client_addr| + let ping_transport = transport.clone() + .and_then(move |out, endpoint, client_addr| { + let node_index = out.node_index; upgrade::apply(out.socket, ping::Ping, endpoint, client_addr) - ) - .and_then(move |out, _, client_addr| { - client_addr.map(|client_addr| { - let out = FinalUpgrade::from((out, client_addr.clone())); - (out, future::ok(client_addr)) - }) + .map(move |(stream, addr)| (FinalUpgrade::from((node_index, stream)), addr)) + }); + + let identify_transport = transport + .and_then(move |out, endpoint, client_addr| { + let node_index = out.node_index; + upgrade::apply(out.socket, IdentifyProtocolConfig, endpoint, client_addr) + .map(move |(id, addr)| { + let fin = match id { + IdentifyOutput::RemoteInfo { info, observed_addr } => + FinalUpgrade::IdentifyDialer(node_index, info, observed_addr), + IdentifyOutput::Sender { .. } => unreachable!("can't reach that on the dialer side"), + }; + (fin, addr) + }) }); - let fut = Interval::new(Instant::now(), Duration::from_secs(30)) + let fut = Interval::new(Instant::now() + Duration::from_secs(5), Duration::from_secs(30)) .map_err(|err| IoError::new(IoErrorKind::Other, err)) - .for_each(move |_| - ping_all(shared.clone(), transport.clone(), &swarm_controller)) + .for_each(move |_| periodic_updates( + shared.clone(), + ping_transport.clone(), + identify_transport.clone(), + &swarm_controller + )) .then(|val| { - warn!(target: "sub-libp2p", "Pinging stream has stopped: {:?}", val); + warn!(target: "sub-libp2p", "Periodic updates stream has stopped: {:?}", val); val }); @@ -1286,29 +1212,34 @@ fn start_pinger( } /// Pings all the nodes we're connected to and disconnects any node that -/// doesn't respond. Returns a `Future` when all the pings have either -/// suceeded or timed out. -fn ping_all( +/// doesn't respond. Identifies nodes that need to be identified. Returns +/// a `Future` when all the pings have either suceeded or timed out. +fn periodic_updates( shared: Arc, - transport: T, + ping_transport: Tp, + identify_transport: Tid, swarm_controller: &SwarmController ) -> impl Future - where T: MuxedTransport> + Clone + 'static, - T::MultiaddrFuture: 'static, + where Tp: MuxedTransport> + Clone + 'static, + Tp::MultiaddrFuture: 'static, + Tid: MuxedTransport> + Clone + 'static, + Tid::MultiaddrFuture: 'static, St: MuxedTransport> + Clone + 'static, C: 'static { + trace!(target: "sub-libp2p", "Periodic update cycle"); + let mut ping_futures = Vec::new(); - for (peer, who, pinger) in shared.network_state.cleanup_and_prepare_ping() { + for PeriodicUpdate { node_index, peer_id, address, pinger, identify } in + shared.network_state.cleanup_and_prepare_updates() { let shared = shared.clone(); - let addr = Multiaddr::from(AddrComponent::P2P(who.clone().into_bytes())); let fut = pinger - .dial(&swarm_controller, &addr, transport.clone()) + .dial(&swarm_controller, &address, ping_transport.clone()) .and_then(move |mut p| { - trace!(target: "sub-libp2p", "Pinging peer #{} aka. {:?}", peer, who); + trace!(target: "sub-libp2p", "Pinging peer #{} aka. {:?}", node_index, peer_id); p.ping() - .map(|()| who) + .map(move |()| peer_id) .map_err(|err| IoError::new(IoErrorKind::Other, err)) }); let ping_start_time = Instant::now(); @@ -1316,21 +1247,27 @@ fn ping_all( .then(move |val| match val { Err(err) => { - trace!(target: "sub-libp2p", "Error while pinging #{:?} => {:?}", peer, err); - shared.network_state.report_ping_failed(peer); + trace!(target: "sub-libp2p", "Error while pinging #{:?} => {:?}", node_index, err); + shared.network_state.report_ping_failed(node_index); // Return Ok, otherwise we would close the ping service Ok(()) }, Ok(who) => { let elapsed = ping_start_time.elapsed(); - trace!(target: "sub-libp2p", "Pong from #{:?} in {:?}", peer, elapsed); - shared.network_state.report_ping_duration(peer, elapsed); + trace!(target: "sub-libp2p", "Pong from #{:?} in {:?}", who, elapsed); + shared.network_state.report_ping_duration(node_index, elapsed); shared.kad_system.update_kbuckets(who); Ok(()) } } ); ping_futures.push(fut); + + if identify { + // Ignore dialing errors, as identifying is only about diagnostics. + trace!(target: "sub-libp2p", "Attempting to identify #{}", node_index); + let _ = swarm_controller.dial(address, identify_transport.clone()); + } } let future = future::loop_fn(ping_futures, |ping_futures| { @@ -1349,22 +1286,6 @@ fn ping_all( Box::new(future) as Box> } -/// Expects a multiaddr of the format `/p2p/` and returns the node ID. -/// Panics if the format is not correct. -fn p2p_multiaddr_to_node_id(client_addr: Multiaddr) -> PeerstorePeerId { - 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") - } -} - /// 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)] diff --git a/substrate/network-libp2p/src/topology.rs b/substrate/network-libp2p/src/topology.rs new file mode 100644 index 0000000000000..8ac0acd858031 --- /dev/null +++ b/substrate/network-libp2p/src/topology.rs @@ -0,0 +1,623 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see .? + +use fnv::FnvHashMap; +use parking_lot::Mutex; +use libp2p::{Multiaddr, PeerId}; +use serde_json; +use std::{cmp, fs}; +use std::io::{Read, Cursor, Error as IoError, ErrorKind as IoErrorKind, Write}; +use std::path::{Path, PathBuf}; +use std::time::{Duration, Instant, SystemTime}; + +/// For each address we're connected to, a period of this duration increases the score by 1. +const CONNEC_DURATION_PER_SCORE: Duration = Duration::from_secs(10); +/// Maximum value for the score. +const MAX_SCORE: u32 = 100; +/// Initial score that a node discovered through Kademlia receives. +const KADEMLIA_DISCOVERY_INITIAL_SCORE: u32 = 10; +/// Score adjustement when we fail to connect to an address. +const SCORE_DIFF_ON_FAILED_TO_CONNECT: i32 = -1; +/// Default time-to-live for addresses discovered through Kademlia. +/// After this time has elapsed and no connection has succeeded, the address will be removed. +const KADEMLIA_DISCOVERY_EXPIRATION: Duration = Duration::from_secs(2 * 3600); +/// After a successful connection, the TTL is set to a minimum at this amount. +const EXPIRATION_PUSH_BACK_CONNEC: Duration = Duration::from_secs(2 * 3600); +/// Initial score that a bootstrap node receives when registered. +const BOOTSTRAP_NODE_SCORE: u32 = 100; +/// Time to live of a boostrap node. This only applies if you start the node later *without* +/// that bootstrap node configured anymore. +const BOOTSTRAP_NODE_EXPIRATION: Duration = Duration::from_secs(24 * 3600); +/// The first time we fail to connect to an address, wait this duration before trying again. +const FIRST_CONNECT_FAIL_BACKOFF: Duration = Duration::from_secs(2); +/// Every time we fail to connect to an address, multiply the backoff by this constant. +const FAIL_BACKOFF_MULTIPLIER: u32 = 2; +/// We need a maximum value for the backoff, overwise we risk an overflow. +const MAX_BACKOFF: Duration = Duration::from_secs(30 * 60); + +// TODO: should be merged with the Kademlia k-buckets + +/// Stores information about the topology of the network. +#[derive(Debug)] +pub struct NetTopology { + store: FnvHashMap, + cache_path: Option, +} + +impl Default for NetTopology { + #[inline] + fn default() -> NetTopology { + NetTopology::memory() + } +} + +impl NetTopology { + /// Initializes a new `NetTopology` that isn't tied to any file. + /// + /// `flush_to_disk()` will be a no-op. + #[inline] + pub fn memory() -> NetTopology { + NetTopology { + store: Default::default(), + cache_path: None, + } + } + + /// Builds a `NetTopology` that will use `path` as a cache. + /// + /// This function tries to load a known topology from the file. If the file doesn't exist + /// or contains garbage data, the execution still continues. + /// + /// Calling `flush_to_disk()` in the future writes to the given path. + pub fn from_file>(path: P) -> NetTopology { + let path = path.as_ref(); + debug!(target: "sub-libp2p", "Initializing peer store for JSON file {:?}", path); + NetTopology { + store: try_load(path), + cache_path: Some(path.to_owned()), + } + } + + /// Writes the topology into the path passed to `from_file`. + /// + /// No-op if the object was created with `memory()`. + pub fn flush_to_disk(&self) -> Result<(), IoError> { + let path = match self.cache_path { + Some(ref p) => p, + None => return Ok(()) + }; + + let file = fs::File::create(path)?; + serialize(file, &self.store) + } + + /// Perform a cleanup pass, removing all obsolete addresses and peers. + /// + /// This should be done from time to time. + pub fn cleanup(&mut self) { + let now_systime = SystemTime::now(); + self.store.retain(|_, peer| { + peer.addrs.retain(|a| { + a.expires > now_systime + }); + !peer.addrs.is_empty() + }); + } + + /// Returns a list of all the known peers. + pub fn peers(&self) -> impl Iterator { + self.store.keys() + } + + /// Returns the known potential addresses of a peer, ordered by score. + /// + /// If we're already connected to that peer, the address(es) we're connected with will be at + /// the top of the list. + // TODO: filter out backed off ones? + pub fn addrs_of_peer(&self, peer: &PeerId) -> impl Iterator { + let peer = if let Some(peer) = self.store.get(peer) { + peer + } else { + // TODO: use an EitherIterator or something + return Vec::new().into_iter(); + }; + + let now = SystemTime::now(); + let mut list = peer.addrs.iter().filter_map(move |addr| { + let (score, connected) = addr.score_and_is_connected(); + if (addr.expires >= now && score > 0) || connected { + Some((score, &addr.addr)) + } else { + None + } + }).collect::>(); + list.sort_by(|a, b| a.0.cmp(&b.0)); + // TODO: meh, optimize + let l = list.into_iter().map(|(_, addr)| addr).collect::>(); + l.into_iter() + } + + /// Returns a list of all the known addresses of peers, ordered by the + /// order in which we should attempt to connect to them. + /// + /// Because of expiration and back-off mechanisms, this list can grow + /// by itself over time. The `Instant` that is returned corresponds to + /// the earlier known time when a new entry will be added automatically to + /// the list. + pub fn addrs_to_attempt(&self) -> (impl Iterator, Instant) { + // TODO: optimize + let now = Instant::now(); + let now_systime = SystemTime::now(); + let mut instant = now + Duration::from_secs(3600); + let mut addrs_out = Vec::new(); + + for (peer, info) in &self.store { + for addr in &info.addrs { + let (score, is_connected) = addr.score_and_is_connected(); + if score == 0 || addr.expires < now_systime { + continue; + } + if !is_connected && addr.back_off_until > now { + instant = cmp::min(instant, addr.back_off_until); + continue; + } + + addrs_out.push(((peer, &addr.addr), score)); + } + } + + addrs_out.sort_by(|a, b| b.1.cmp(&a.1)); + (addrs_out.into_iter().map(|a| a.0), instant) + } + + /// Adds an address corresponding to a boostrap node. + /// + /// We assume that the address is valid, so its score starts very high. + pub fn add_bootstrap_addr(&mut self, peer: &PeerId, addr: Multiaddr) { + let now_systime = SystemTime::now(); + let now = Instant::now(); + + let peer = peer_access(&mut self.store, peer); + + let mut found = false; + peer.addrs.retain(|a| { + if a.expires < now_systime { + return false; + } + if a.addr == addr { + found = true; + } + true + }); + + if !found { + peer.addrs.push(Addr { + addr, + expires: now_systime + BOOTSTRAP_NODE_EXPIRATION, + back_off_until: now, + next_back_off: FIRST_CONNECT_FAIL_BACKOFF, + score: Mutex::new(AddrScore { + connected_since: None, + score: BOOTSTRAP_NODE_SCORE, + latest_score_update: now, + }), + }); + } + } + + /// Adds an address discovered through the Kademlia DHT. + /// + /// This address is not necessarily valid and should expire after a TTL. + pub fn add_kademlia_discovered_addr(&mut self, peer_id: &PeerId, addr: Multiaddr) { + let now_systime = SystemTime::now(); + let now = Instant::now(); + + let peer = peer_access(&mut self.store, peer_id); + + let mut found = false; + peer.addrs.retain(|a| { + if a.expires < now_systime { + return false; + } + if a.addr == addr { + found = true; + } + true + }); + + if !found { + trace!(target: "sub-libp2p", "Peer store: adding address {} for {:?}", addr, peer_id); + peer.addrs.push(Addr { + addr, + expires: now_systime + KADEMLIA_DISCOVERY_EXPIRATION, + back_off_until: now, + next_back_off: FIRST_CONNECT_FAIL_BACKOFF, + score: Mutex::new(AddrScore { + connected_since: None, + score: KADEMLIA_DISCOVERY_INITIAL_SCORE, + latest_score_update: now, + }), + }); + } + } + + /// Indicates the peer store that we're connected to this given address. + /// + /// This increases the score of the address that we connected to. Since we assume that only + /// one peer can be reached with any specific address, we also remove all addresses from other + /// peers that match the one we connected to. + pub fn report_connected(&mut self, addr: &Multiaddr, peer: &PeerId) { + let now = Instant::now(); + + // Just making sure that we have an entry for this peer in `store`, but don't use it. + let _ = peer_access(&mut self.store, peer); + + for (peer_in_store, info_in_store) in self.store.iter_mut() { + if peer == peer_in_store { + if let Some(addr) = info_in_store.addrs.iter_mut().find(|a| &a.addr == addr) { + addr.connected_now(); + addr.back_off_until = now; + addr.next_back_off = FIRST_CONNECT_FAIL_BACKOFF; + continue; + } + + // TODO: a else block would be better, but we get borrowck errors + info_in_store.addrs.push(Addr { + addr: addr.clone(), + expires: SystemTime::now() + EXPIRATION_PUSH_BACK_CONNEC, + back_off_until: now, + next_back_off: FIRST_CONNECT_FAIL_BACKOFF, + score: Mutex::new(AddrScore { + connected_since: Some(now), + latest_score_update: now, + score: KADEMLIA_DISCOVERY_INITIAL_SCORE + }), + }); + + } else { + // Set the score to 0 for any address that matches the one we connected to. + for addr_in_store in &mut info_in_store.addrs { + if &addr_in_store.addr == addr { + addr_in_store.adjust_score(-(MAX_SCORE as i32)); + } + } + } + } + } + + /// Indicates the peer store that we're disconnected from an address. + /// + /// There's no need to indicate a peer ID, as each address can only have one peer ID. + /// If we were indeed connected to this addr, then we can find out which peer ID it is. + pub fn report_disconnected(&mut self, addr: &Multiaddr, reason: DisconnectReason) { + let score_diff = match reason { + DisconnectReason::ClosedGracefully => -1, + }; + + for info in self.store.values_mut() { + for a in info.addrs.iter_mut() { + if &a.addr == addr { + a.disconnected_now(score_diff); + a.back_off_until = Instant::now() + a.next_back_off; + a.next_back_off = cmp::min(a.next_back_off * FAIL_BACKOFF_MULTIPLIER, MAX_BACKOFF); + let expires_push_back = SystemTime::now() + EXPIRATION_PUSH_BACK_CONNEC; + if a.expires < expires_push_back { + a.expires = expires_push_back; + } + return; + } + } + } + } + + /// Indicates the peer store that we failed to connect to an address. + /// + /// We don't care about which peer is supposed to be behind that address. If we failed to dial + /// it for a specific peer, we would also fail to dial it for all peers that have this + /// address. + pub fn report_failed_to_connect(&mut self, addr: &Multiaddr) { + for info in self.store.values_mut() { + for a in info.addrs.iter_mut() { + if &a.addr == addr { + a.adjust_score(SCORE_DIFF_ON_FAILED_TO_CONNECT); + a.back_off_until = Instant::now() + a.next_back_off; + a.next_back_off = cmp::min(a.next_back_off * FAIL_BACKOFF_MULTIPLIER, MAX_BACKOFF); + } + } + } + } +} + +/// Reason why we disconnected from a peer. +pub enum DisconnectReason { + /// The disconnection was graceful. + ClosedGracefully, +} + +fn peer_access<'a>(store: &'a mut FnvHashMap, peer: &PeerId) -> &'a mut PeerInfo { + // TODO: should be optimizable if HashMap gets a better API + store.entry(peer.clone()).or_insert_with(Default::default) +} + +#[derive(Debug, Clone, Default)] +struct PeerInfo { + /// Addresses of that peer. + addrs: Vec, +} + +#[derive(Debug)] +struct Addr { + /// The multiaddress. + addr: Multiaddr, + /// When the address expires. + expires: SystemTime, + next_back_off: Duration, + /// Don't try to connect to this node until `Instant`. + back_off_until: Instant, + score: Mutex, +} + +impl Clone for Addr { + fn clone(&self) -> Addr { + Addr { + addr: self.addr.clone(), + expires: self.expires.clone(), + next_back_off: self.next_back_off.clone(), + back_off_until: self.back_off_until.clone(), + score: Mutex::new(self.score.lock().clone()), + } + } +} + +#[derive(Debug, Clone)] +struct AddrScore { + /// If connected, contains the moment when we connected. `None` if we're not connected. + connected_since: Option, + /// Score of this address. Potentially needs to be updated based on `latest_score_update`. + score: u32, + /// When we last updated the score. + latest_score_update: Instant, +} + +impl Addr { + /// Sets the addr to connected. + fn connected_now(&self) { + let mut score = self.score.lock(); + let now = Instant::now(); + Addr::flush(&mut score, now); + score.connected_since = Some(now); + } + + /// Applies a modification to the score. + fn adjust_score(&self, score_diff: i32) { + let mut score = self.score.lock(); + Addr::flush(&mut score, Instant::now()); + if score_diff >= 0 { + score.score = cmp::min(MAX_SCORE, score.score + score_diff as u32); + } else { + score.score = score.score.saturating_sub(-score_diff as u32); + } + } + + /// Sets the addr to disconnected and applies a modification to the score. + fn disconnected_now(&self, score_diff: i32) { + let mut score = self.score.lock(); + Addr::flush(&mut score, Instant::now()); + score.connected_since = None; + if score_diff >= 0 { + score.score = cmp::min(MAX_SCORE, score.score + score_diff as u32); + } else { + score.score = score.score.saturating_sub(-score_diff as u32); + } + } + + /// Returns the score, and true if we are connected to this addr. + fn score_and_is_connected(&self) -> (u32, bool) { + let mut score = self.score.lock(); + Addr::flush(&mut score, Instant::now()); + let is_connected = score.connected_since.is_some(); + (score.score, is_connected) + } + + /// Updates `score` and `latest_score_update`, and returns the score. + fn score(&self) -> u32 { + let mut score = self.score.lock(); + Addr::flush(&mut score, Instant::now()); + score.score + } + + fn flush(score: &mut AddrScore, now: Instant) { + if let Some(connected_since) = score.connected_since { + let potential_score: u32 = div_dur_with_dur(now - connected_since, CONNEC_DURATION_PER_SCORE); + // We flush when we connect to an address. + debug_assert!(score.latest_score_update >= connected_since); + let effective_score: u32 = + div_dur_with_dur(score.latest_score_update - connected_since, CONNEC_DURATION_PER_SCORE); + let to_add = potential_score.saturating_sub(effective_score); + score.score = cmp::min(MAX_SCORE, score.score + to_add); + } + + score.latest_score_update = now; + } +} + +/// Divides a `Duration` with a `Duration`. This exists in the stdlib but isn't stable yet. +// TODO: remove this function once stable +fn div_dur_with_dur(a: Duration, b: Duration) -> u32 { + let a_ms = a.as_secs() * 1_000_000 + (a.subsec_nanos() / 1_000) as u64; + let b_ms = b.as_secs() * 1_000_000 + (b.subsec_nanos() / 1_000) as u64; + (a_ms / b_ms) as u32 +} + +/// Serialized version of a `PeerInfo`. Suitable for storage in the cache file. +#[derive(Debug, Clone, Serialize, Deserialize)] +struct SerializedPeerInfo { + addrs: Vec, +} + +/// Serialized version of an `Addr`. Suitable for storage in the cache file. +#[derive(Debug, Clone, Serialize, Deserialize)] +struct SerializedAddr { + addr: String, + expires: SystemTime, + score: u32, +} + +impl<'a> From<&'a Addr> for SerializedAddr { + fn from(addr: &'a Addr) -> SerializedAddr { + SerializedAddr { + addr: addr.addr.to_string(), + expires: addr.expires, + score: addr.score(), + } + } +} + +/// Attempts to load storage from a file. +/// Deletes the file and returns an empty map if the file doesn't exist, cannot be opened +/// or is corrupted. +fn try_load(path: impl AsRef) -> FnvHashMap { + let path = path.as_ref(); + if !path.exists() { + debug!(target: "sub-libp2p", "Peer storage file {:?} doesn't exist", path); + return Default::default() + } + + let mut file = match fs::File::open(path) { + Ok(f) => f, + Err(err) => { + warn!(target: "sub-libp2p", "Failed to open peer storage file: {:?}", err); + info!(target: "sub-libp2p", "Deleting peer storage file {:?}", path); + let _ = fs::remove_file(path); + return Default::default() + } + }; + + // We want to support empty files (and treat them as an empty recordset). Unfortunately + // `serde_json` will always produce an error if we do this ("unexpected EOF at line 0 + // column 0"). Therefore we start by reading one byte from the file in order to check + // for EOF. + + let mut first_byte = [0]; + let num_read = match file.read(&mut first_byte) { + Ok(f) => f, + Err(err) => { + // TODO: DRY + warn!(target: "sub-libp2p", "Failed to read peer storage file: {:?}", err); + info!(target: "sub-libp2p", "Deleting peer storage file {:?}", path); + let _ = fs::remove_file(path); + return Default::default() + } + }; + + if num_read == 0 { + // File is empty. + debug!(target: "sub-libp2p", "Peer storage file {:?} is empty", path); + Default::default() + + } else { + let data = Cursor::new(first_byte).chain(file); + match serde_json::from_reader::<_, serde_json::Value>(data) { + Ok(serde_json::Value::Null) => Default::default(), + Ok(serde_json::Value::Object(map)) => deserialize_tolerant(map.into_iter()), + Ok(_) | Err(_) => { + // The `Ok(_)` case means that the file doesn't contain a map. + let _ = fs::remove_file(path); + Default::default() + }, + } + } +} + +/// Attempts to turn a deserialized version of the storage into the final version. +/// +/// Skips entries that are invalid. +fn deserialize_tolerant( + iter: impl Iterator +) -> FnvHashMap { + let now = Instant::now(); + let now_systime = SystemTime::now(); + + let mut out = FnvHashMap::default(); + for (peer, info) in iter { + let peer: PeerId = match peer.parse() { + Ok(p) => p, + Err(_) => continue, + }; + + let info: SerializedPeerInfo = match serde_json::from_value(info) { + Ok(i) => i, + Err(_) => continue, + }; + + let mut addrs = Vec::with_capacity(info.addrs.len()); + for addr in info.addrs { + let multiaddr = match addr.addr.parse() { + Ok(a) => a, + Err(_) => continue, + }; + + if addr.expires < now_systime { + continue + } + + addrs.push(Addr { + addr: multiaddr, + expires: addr.expires, + next_back_off: FIRST_CONNECT_FAIL_BACKOFF, + back_off_until: now, + score: Mutex::new(AddrScore { + connected_since: None, + score: addr.score, + latest_score_update: now, + }), + }); + } + + if addrs.is_empty() { + continue; + } + + out.insert(peer, PeerInfo { addrs }); + } + + out +} + +/// Attempts to turn a deserialized version of the storage into the final version. +/// +/// Skips entries that are invalid or expired. +fn serialize(out: W, map: &FnvHashMap) -> Result<(), IoError> { + let now = SystemTime::now(); + let array: FnvHashMap<_, _> = map.iter().filter_map(|(peer, info)| { + if info.addrs.is_empty() { + return None + } + + let peer = peer.to_base58(); + let info = SerializedPeerInfo { + addrs: info.addrs.iter() + .filter(|a| a.expires > now) + .map(Into::into) + .collect(), + }; + + Some((peer, info)) + }).collect(); + + serde_json::to_writer_pretty(out, &array) + .map_err(|err| IoError::new(IoErrorKind::Other, err)) +} diff --git a/substrate/network-libp2p/src/transport.rs b/substrate/network-libp2p/src/transport.rs index 02315a4cea455..d193b642e9361 100644 --- a/substrate/network-libp2p/src/transport.rs +++ b/substrate/network-libp2p/src/transport.rs @@ -14,58 +14,36 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use libp2p::{self, Transport, mplex, secio, yamux}; +use libp2p::{self, PeerId, Transport, mplex, secio, yamux}; use libp2p::core::{MuxedTransport, either, upgrade}; use libp2p::transport_timeout::TransportTimeout; use std::time::Duration; +use std::usize; use tokio_io::{AsyncRead, AsyncWrite}; /// Builds the transport that serves as a common ground for all connections. pub fn build_transport( - unencrypted_allowed: UnencryptedAllowed, local_private_key: secio::SecioKeyPair -) -> impl MuxedTransport + Clone { - let base = libp2p::CommonTransport::new() - .with_upgrade({ - let secio = secio::SecioConfig { - key: local_private_key, - }; - - let mut plaintext = upgrade::toggleable(upgrade::PlainTextConfig); - match unencrypted_allowed { - UnencryptedAllowed::Allowed => plaintext.disable(), - UnencryptedAllowed::Denied => (), - }; +) -> impl MuxedTransport + Clone { + let mut mplex_config = mplex::MplexConfig::new(); + mplex_config.max_buffer_len_behaviour(mplex::MaxBufferBehaviour::Block); + mplex_config.max_buffer_len(usize::MAX); - // TODO: this `EitherOutput` thing shows that libp2p's API could be improved - upgrade::or( - upgrade::map(plaintext, |out| - (either::EitherOutput::First(out), None) - ), - upgrade::map(secio, |out: secio::SecioOutput<_>| - (either::EitherOutput::Second(out.stream), - Some(out.remote_key)) - ), - ) + let base = libp2p::CommonTransport::new() + .with_upgrade(secio::SecioConfig { + key: local_private_key, + }) + .and_then(move |out, endpoint, client_addr| { + let upgrade = upgrade::or( + upgrade::map(mplex_config, either::EitherOutput::First), + upgrade::map(yamux::Config::default(), either::EitherOutput::Second), + ); + let key = out.remote_key; + let upgrade = upgrade::map(upgrade, move |muxer| (key, muxer)); + upgrade::apply(out.stream, upgrade, endpoint, client_addr) }) - // TODO: check that the public key matches what is reported by identify - .map(|(socket, _key), _| socket) - // TODO: this `EitherOutput` thing shows that libp2p's API could be improved - .with_upgrade(upgrade::or( - upgrade::map(mplex::MplexConfig::new(), either::EitherOutput::First), - upgrade::map(yamux::Config::default(), either::EitherOutput::Second), - )) - .map(|out, _| ((), out)) .into_connection_reuse() - .map(|((), out), _| out); + .map(|(key, substream), _| (key.into_peer_id(), substream)); TransportTimeout::new(base, Duration::from_secs(20)) } - -/// Specifies whether unencrypted communications are allowed or denied. -#[derive(Debug, Copy, Clone)] -pub enum UnencryptedAllowed { - #[allow(dead_code)] - Allowed, - Denied, -}