From 1b63d6234c67769d3322b5f7ec041e2175aadcbf Mon Sep 17 00:00:00 2001
From: Marek Kotewicz <marek.kotewicz@gmail.com>
Date: Thu, 4 Apr 2019 19:40:40 +0200
Subject: [PATCH] simplification of peerset api (#2123)

* Introduction of PeersetHandle

* integrate PeersetHandle with the rest of the codebase

* fix compilation errors

* more tests for peerset, fixed overwriting bug in add_reserved_peer

* Slots data structure and bugfixes for peerset

* bend to pressure

* updated lru-cache to 0.1.2 and updated linked-hash-map to 0.5.2

* peerset discovered list is now a LinkedHashMap

* fix review suggestions

* split back Peerset and PeersetHandle

* test for Peerset::discovered

* applied review suggestions

* fixes to peerset::incoming

* peerset disconnects are all instantaneous

* instantaneous drop in peerset finished

* Peerset::set_reserved_only can also reconnect nodes

* Peerset scores cache uses lru-cache

* remove redundant function call and comment from Peerset::on_set_reserved_only

* add_peer returns SlotState enum

* apply review suggestions

* is_reserved -> is_connected_and_reserved
---
 Cargo.lock                                    | 260 ++++---
 core/network-libp2p/src/behaviour.rs          |   2 +-
 .../src/custom_proto/behaviour.rs             |  16 +-
 core/network-libp2p/src/service_task.rs       |   8 +-
 core/network/src/service.rs                   |   8 +-
 core/peerset/Cargo.toml                       |   8 +-
 core/peerset/src/lib.rs                       | 706 ++++++++++++++----
 core/peerset/src/slots.rs                     | 148 ++++
 8 files changed, 856 insertions(+), 300 deletions(-)
 create mode 100644 core/peerset/src/slots.rs

diff --git a/Cargo.lock b/Cargo.lock
index 49ebdf1ba5..a72c47fbce 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -677,7 +677,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "elastic-array"
-version = "0.10.0"
+version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -758,8 +758,8 @@ dependencies = [
  "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec-derive 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -798,7 +798,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "fork-tree"
 version = "1.0.0"
 dependencies = [
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -903,7 +903,7 @@ dependencies = [
 
 [[package]]
 name = "hash-db"
-version = "0.12.0"
+version = "0.12.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -923,6 +923,11 @@ dependencies = [
  "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "hashmap_core"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "heapsize"
 version = "0.4.2"
@@ -1072,7 +1077,7 @@ name = "impl-codec"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1207,7 +1212,7 @@ name = "keccak-hasher"
 version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "hash256-std-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1226,7 +1231,7 @@ name = "kvdb"
 version = "0.1.0"
 source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d"
 dependencies = [
- "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)",
 ]
 
@@ -1244,7 +1249,7 @@ name = "kvdb-rocksdb"
 version = "0.1.4"
 source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d"
 dependencies = [
- "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "fs-swap 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)",
@@ -1648,12 +1653,7 @@ dependencies = [
 
 [[package]]
 name = "linked-hash-map"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "linked-hash-map"
-version = "0.5.1"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1661,7 +1661,7 @@ name = "linked_hash_set"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1691,10 +1691,10 @@ dependencies = [
 
 [[package]]
 name = "lru-cache"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1723,10 +1723,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "memory-db"
-version = "0.12.0"
+version = "0.12.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hashmap_core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1877,7 +1878,7 @@ dependencies = [
  "node-executor 1.0.0",
  "node-primitives 1.0.0",
  "node-runtime 1.0.0",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
  "sr-primitives 1.0.0",
  "structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1903,7 +1904,7 @@ version = "1.0.0"
 dependencies = [
  "node-primitives 1.0.0",
  "node-runtime 1.0.0",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
  "sr-primitives 1.0.0",
  "srml-balances 1.0.0",
@@ -1922,7 +1923,7 @@ dependencies = [
  "substrate-primitives 1.0.0",
  "substrate-state-machine 1.0.0",
  "substrate-trie 1.0.0",
- "trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trie-root 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1930,8 +1931,8 @@ dependencies = [
 name = "node-primitives"
 version = "1.0.0"
 dependencies = [
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec-derive 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1948,7 +1949,7 @@ dependencies = [
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "node-primitives 1.0.0",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1991,7 +1992,7 @@ dependencies = [
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "node-template-runtime 1.0.0",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
  "substrate-basic-authorship 1.0.0",
@@ -2005,7 +2006,7 @@ dependencies = [
  "substrate-service 1.0.0",
  "substrate-transaction-pool 1.0.0",
  "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trie-root 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2013,7 +2014,7 @@ dependencies = [
 name = "node-template-runtime"
 version = "1.0.0"
 dependencies = [
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2151,17 +2152,17 @@ source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7
 
 [[package]]
 name = "parity-codec"
-version = "3.2.0"
+version = "3.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec-derive 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "parity-codec-derive"
-version = "3.1.0"
+version = "3.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2669,8 +2670,8 @@ dependencies = [
  "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec-derive 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -3007,9 +3008,9 @@ name = "sr-io"
 version = "1.0.0"
 dependencies = [
  "environmental 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-std 1.0.0",
  "substrate-primitives 1.0.0",
@@ -3025,7 +3026,7 @@ dependencies = [
  "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3039,7 +3040,7 @@ name = "sr-sandbox"
 version = "1.0.0"
 dependencies = [
  "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-std 1.0.0",
  "substrate-primitives 1.0.0",
@@ -3059,7 +3060,7 @@ name = "sr-version"
 version = "1.0.0"
 dependencies = [
  "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-primitives 1.0.0",
@@ -3071,7 +3072,7 @@ name = "srml-assets"
 version = "1.0.0"
 dependencies = [
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
  "sr-primitives 1.0.0",
@@ -3087,8 +3088,8 @@ version = "1.0.0"
 dependencies = [
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec-derive 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
@@ -3109,7 +3110,7 @@ name = "srml-balances"
 version = "1.0.0"
 dependencies = [
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
@@ -3126,7 +3127,7 @@ name = "srml-consensus"
 version = "1.0.0"
 dependencies = [
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
@@ -3144,7 +3145,7 @@ version = "1.0.0"
 dependencies = [
  "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3167,8 +3168,8 @@ name = "srml-council"
 version = "1.0.0"
 dependencies = [
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec-derive 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
@@ -3186,7 +3187,7 @@ name = "srml-democracy"
 version = "1.0.0"
 dependencies = [
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3204,7 +3205,7 @@ name = "srml-example"
 version = "1.0.0"
 dependencies = [
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
  "sr-primitives 1.0.0",
@@ -3219,8 +3220,8 @@ name = "srml-executive"
 version = "1.0.0"
 dependencies = [
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec-derive 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
  "sr-primitives 1.0.0",
@@ -3238,7 +3239,7 @@ version = "1.0.0"
 dependencies = [
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3255,7 +3256,7 @@ dependencies = [
 name = "srml-grandpa"
 version = "1.0.0"
 dependencies = [
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
@@ -3275,8 +3276,8 @@ name = "srml-indices"
 version = "1.0.0"
 dependencies = [
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec-derive 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3293,7 +3294,7 @@ dependencies = [
 name = "srml-metadata"
 version = "1.0.0"
 dependencies = [
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-std 1.0.0",
@@ -3306,8 +3307,8 @@ version = "1.0.0"
 dependencies = [
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec-derive 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
@@ -3325,7 +3326,7 @@ name = "srml-staking"
 version = "1.0.0"
 dependencies = [
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
@@ -3346,8 +3347,8 @@ name = "srml-sudo"
 version = "1.0.0"
 dependencies = [
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec-derive 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
  "sr-primitives 1.0.0",
@@ -3365,7 +3366,7 @@ dependencies = [
  "bitmask 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3413,7 +3414,7 @@ dependencies = [
 name = "srml-support-test"
 version = "0.1.0"
 dependencies = [
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
@@ -3427,7 +3428,7 @@ name = "srml-system"
 version = "1.0.0"
 dependencies = [
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3443,7 +3444,7 @@ name = "srml-timestamp"
 version = "1.0.0"
 dependencies = [
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
  "sr-primitives 1.0.0",
@@ -3459,7 +3460,7 @@ name = "srml-treasury"
 version = "1.0.0"
 dependencies = [
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
@@ -3614,7 +3615,7 @@ name = "substrate-basic-authorship"
 version = "1.0.0"
 dependencies = [
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-primitives 1.0.0",
  "substrate-client 1.0.0",
  "substrate-consensus-aura-primitives 1.0.0",
@@ -3678,13 +3679,13 @@ dependencies = [
  "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)",
  "kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-api-macros 1.0.0",
  "sr-primitives 1.0.0",
@@ -3706,13 +3707,13 @@ name = "substrate-client-db"
 version = "1.0.0"
 dependencies = [
  "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)",
  "kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)",
  "kvdb-rocksdb 0.1.4 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-primitives 1.0.0",
  "substrate-client 1.0.0",
@@ -3734,7 +3735,7 @@ dependencies = [
  "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
  "sr-primitives 1.0.0",
@@ -3773,7 +3774,7 @@ dependencies = [
  "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-primitives 1.0.0",
  "substrate-client 1.0.0",
@@ -3788,7 +3789,7 @@ dependencies = [
 name = "substrate-consensus-authorities"
 version = "1.0.0"
 dependencies = [
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
  "sr-primitives 1.0.0",
  "sr-std 1.0.0",
@@ -3807,8 +3808,8 @@ dependencies = [
  "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "libp2p 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec-derive 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-primitives 1.0.0",
  "sr-version 1.0.0",
  "substrate-inherents 1.0.0",
@@ -3825,7 +3826,7 @@ dependencies = [
  "exit-future 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rhododendron 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
@@ -3853,7 +3854,7 @@ dependencies = [
  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3878,7 +3879,7 @@ dependencies = [
  "fork-tree 1.0.0",
  "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-primitives 1.0.0",
@@ -3900,7 +3901,7 @@ dependencies = [
 name = "substrate-finality-grandpa-primitives"
 version = "1.0.0"
 dependencies = [
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-primitives 1.0.0",
  "sr-std 1.0.0",
  "substrate-client 1.0.0",
@@ -3911,7 +3912,7 @@ dependencies = [
 name = "substrate-inherents"
 version = "1.0.0"
 dependencies = [
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-primitives 1.0.0",
  "sr-std 1.0.0",
@@ -3954,11 +3955,11 @@ dependencies = [
  "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fork-tree 1.0.0",
  "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "linked_hash_set 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4007,7 +4008,7 @@ dependencies = [
  "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-primitives 1.0.0",
  "substrate-client 1.0.0",
  "substrate-consensus-common 1.0.0",
@@ -4039,16 +4040,12 @@ dependencies = [
 name = "substrate-peerset"
 version = "1.0.0"
 dependencies = [
- "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "libp2p 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -4058,13 +4055,13 @@ dependencies = [
  "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "hash256-std-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4096,7 +4093,7 @@ dependencies = [
  "jsonrpc-derive 10.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "jsonrpc-pubsub 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4147,7 +4144,7 @@ dependencies = [
  "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4196,7 +4193,7 @@ version = "1.0.0"
 dependencies = [
  "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "substrate-primitives 1.0.0",
 ]
@@ -4205,17 +4202,17 @@ dependencies = [
 name = "substrate-state-machine"
 version = "1.0.0"
 dependencies = [
- "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "substrate-panic-handler 1.0.0",
  "substrate-primitives 1.0.0",
  "substrate-trie 1.0.0",
- "trie-db 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trie-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trie-root 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -4240,7 +4237,7 @@ name = "substrate-test-client"
 version = "1.0.0"
 dependencies = [
  "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-primitives 1.0.0",
  "substrate-client 1.0.0",
  "substrate-client-db 1.0.0",
@@ -4259,7 +4256,7 @@ dependencies = [
  "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-io 1.0.0",
@@ -4288,7 +4285,7 @@ dependencies = [
  "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4304,7 +4301,7 @@ dependencies = [
  "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "sr-primitives 1.0.0",
  "substrate-client 1.0.0",
@@ -4319,15 +4316,15 @@ name = "substrate-trie"
 version = "1.0.0"
 dependencies = [
  "criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "keccak-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "memory-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memory-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "substrate-primitives 1.0.0",
  "trie-bench 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "trie-db 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trie-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trie-root 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "trie-standardmap 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -4699,32 +4696,33 @@ version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "keccak-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "memory-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "trie-db 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memory-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trie-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trie-root 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "trie-standardmap 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "trie-db"
-version = "0.12.1"
+version = "0.12.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hashmap_core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "trie-root"
-version = "0.12.0"
+version = "0.12.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -4733,7 +4731,7 @@ version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "keccak-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -5172,7 +5170,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea"
 "checksum ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81956bcf7ef761fb4e1d88de3fa181358a0d26cbcb9755b587a08f9119824b86"
 "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 elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "073be79b6538296faf81c631872676600616073817dd9a440c477ad09b408983"
 "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e"
 "checksum environmental 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c7464757b80de8930c91c9afe77ddce501826bf9d134a87db2c67d9dc177e2c"
 "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02"
@@ -5198,9 +5196,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
 "checksum globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4743617a7464bbda3c8aec8558ff2f9429047e025771037df561d383337ff865"
 "checksum h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb2b25a33e231484694267af28fec74ac63b5ccf51ee2065a5e313b834d836e"
-"checksum hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07463834729d0ce8d475e7dd6d302e407093ad9a9c02d77eb07fb74b5373829d"
+"checksum hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ba7fb417e5c470acdd61068c79767d0e65962e70836cf6c9dfd2409f06345ce0"
 "checksum hash256-std-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1224388a21c88a80ae7087a2a245ca6d80acc97a9186b75789fb3eeefd0609af"
 "checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da"
+"checksum hashmap_core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8e04cb7a5051270ef3fa79f8c7604d581ecfa73d520e74f554e45541c4b5881a"
 "checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461"
 "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
 "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
@@ -5260,18 +5259,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum libp2p-yamux 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbb8d08cb536a964727e77b868a026c6d92993f08e387d49163565575a478d9"
 "checksum librocksdb-sys 5.14.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b9024327233e7fac7982440f73301c00046d438c5b1011e8f4e394226ce19007"
 "checksum libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "688e8d65e495567c2c35ea0001b26b9debf0b4ea11f8cccc954233b75fc3428a"
-"checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939"
-"checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e"
+"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
 "checksum linked_hash_set 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7c91c4c7bbeb4f2f7c4e5be11e6a05bd6830bc37249c47ce1ad86ad453ff9c"
 "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
 "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
 "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
-"checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21"
+"checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
 "checksum make-cmd 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8ca8afbe8af1785e09636acb5a41e08a765f5f0340568716c18a8700ba3c0d3"
 "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
 "checksum memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1dd4eaac298c32ce07eb6ed9242eda7d82955b9170b7d6db59b2e02cc63fcb8"
 "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
-"checksum memory-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd87d4d64f7b86d8804bbb419f8ecb187cb8f40a50e91c72848075c604ba88d"
+"checksum memory-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7623b01a4f1b7acb7cf8e3f678f05e15e6ae26cb0b738dfeb5cc186fd6b82ef4"
 "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882"
 "checksum merlin 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a9e97b439f6d38cbe2a4a4aa93f6770c5305f62761b78b1851406c09c87ee2a"
 "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0"
@@ -5299,8 +5297,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
 "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13"
 "checksum parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "<none>"
-"checksum parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21c9c3a1623c71ed83964ff28cac6126e178920f7646d32c337eacb9152b2907"
-"checksum parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "864e9f66b58c0b38f0d6b511b6576afa2b678ae801b64220553bced57ac12df9"
+"checksum parity-codec 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2edd80cdaf3b9c7b7f524299586bb4eae43cc5eb20c7b41aa0cd741200000e38"
+"checksum parity-codec-derive 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00a486fd383382ddcb2de928364b1f82571c1e48274fc43b7667a4738ee4056c"
 "checksum parity-crypto 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b9db194dfbcfe3b398d63d765437a5c7232d59906e203055f0e993f6458ff1"
 "checksum parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61ae6944d4435d41f4d0f12108c5cbb9207cbb14bc8f2b4984c6e930dc9c8e41"
 "checksum parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e8eab0287ccde7821e337a124dc5a4f1d6e4c25d10cc91e3f9361615dd95076"
@@ -5443,8 +5441,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f"
 "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
 "checksum trie-bench 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eafa32a8662c06f5bf135984bc1a12821fd38770b5c2f2f9e8750327fcbe3955"
-"checksum trie-db 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "843af112ba3a8c919cd961edf3cac9272353f5e277ad8678c7023fa70e5c0e2d"
-"checksum trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e45632ecaf2b8b4a40b5208383cd659b4e66f58ccd40086467a4614b45781430"
+"checksum trie-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1ba73747fd3a64ab531274c04cb588dfa9d30d972d62990831e63fbce2cfec59"
+"checksum trie-root 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfa2e20c4f1418ac2e71ddc418e35e1b56e34022e2146209ffdbf1b2de8b1bd9"
 "checksum trie-standardmap 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006314f54f2ea7944a878e66fd93ad7978095bc355f30a2f26ec40f664d86c86"
 "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382"
 "checksum twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d261e83e727c8e2dbb75dacac67c36e35db36a958ee504f2164fc052434e1"
diff --git a/core/network-libp2p/src/behaviour.rs b/core/network-libp2p/src/behaviour.rs
index f93665ce76..e00fba5219 100644
--- a/core/network-libp2p/src/behaviour.rs
+++ b/core/network-libp2p/src/behaviour.rs
@@ -58,7 +58,7 @@ impl<TMessage, TSubstream> Behaviour<TMessage, TSubstream> {
 		local_public_key: PublicKey,
 		protocol: RegisteredProtocol<TMessage>,
 		known_addresses: Vec<(PeerId, Multiaddr)>,
-		peerset: substrate_peerset::PeersetMut,
+		peerset: substrate_peerset::Peerset,
 		enable_mdns: bool,
 	) -> Self {
 		let identify = {
diff --git a/core/network-libp2p/src/custom_proto/behaviour.rs b/core/network-libp2p/src/custom_proto/behaviour.rs
index 4d7a58e7d3..7b896dba84 100644
--- a/core/network-libp2p/src/custom_proto/behaviour.rs
+++ b/core/network-libp2p/src/custom_proto/behaviour.rs
@@ -60,7 +60,7 @@ pub struct CustomProto<TMessage, TSubstream> {
 	protocol: RegisteredProtocol<TMessage>,
 
 	/// Receiver for instructions about who to connect to or disconnect from.
-	peerset: substrate_peerset::PeersetMut,
+	peerset: substrate_peerset::Peerset,
 
 	/// List of peers in our state.
 	peers: FnvHashMap<PeerId, PeerState>,
@@ -204,7 +204,7 @@ impl<TMessage, TSubstream> CustomProto<TMessage, TSubstream> {
 	/// Creates a `CustomProtos`.
 	pub fn new(
 		protocol: RegisteredProtocol<TMessage>,
-		peerset: substrate_peerset::PeersetMut,
+		peerset: substrate_peerset::Peerset,
 	) -> Self {
 		CustomProto {
 			protocol,
@@ -242,7 +242,7 @@ impl<TMessage, TSubstream> CustomProto<TMessage, TSubstream> {
 			// DisabledPendingEnable => Disabled.
 			PeerState::DisabledPendingEnable { open, connected_point, timer } => {
 				debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id);
-				self.peerset.dropped(peer_id);
+				self.peerset.dropped(peer_id.clone());
 				let banned_until = Some(if let Some(ban) = ban {
 					cmp::max(timer.deadline(), Instant::now() + ban)
 				} else {
@@ -254,7 +254,7 @@ impl<TMessage, TSubstream> CustomProto<TMessage, TSubstream> {
 			// Enabled => Disabled.
 			PeerState::Enabled { open, connected_point } => {
 				debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id);
-				self.peerset.dropped(peer_id);
+				self.peerset.dropped(peer_id.clone());
 				debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", peer_id);
 				self.events.push(NetworkBehaviourAction::SendEvent {
 					peer_id: peer_id.clone(),
@@ -513,7 +513,7 @@ impl<TMessage, TSubstream> CustomProto<TMessage, TSubstream> {
 			debug!(target: "sub-libp2p", "PSM => Accept({:?}, {:?}): Obsolete incoming,
 				sending back dropped", index, incoming.peer_id);
 			debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", incoming.peer_id);
-			self.peerset.dropped(&incoming.peer_id);
+			self.peerset.dropped(incoming.peer_id.clone());
 			return
 		}
 
@@ -691,7 +691,7 @@ where
 				debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}): Was disabled \
 					(through {:?}) but pending enable", peer_id, endpoint);
 				debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id);
-				self.peerset.dropped(peer_id);
+				self.peerset.dropped(peer_id.clone());
 				self.peers.insert(peer_id.clone(), PeerState::Banned { until: timer.deadline() });
 				if open {
 					debug!(target: "sub-libp2p", "External API <= Closed({:?})", peer_id);
@@ -708,7 +708,7 @@ where
 				debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}): Was enabled \
 					(through {:?})", peer_id, endpoint);
 				debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id);
-				self.peerset.dropped(peer_id);
+				self.peerset.dropped(peer_id.clone());
 
 				if open {
 					debug!(target: "sub-libp2p", "External API <= Closed({:?})", peer_id);
@@ -759,7 +759,7 @@ where
 						until: Instant::now() + Duration::from_secs(5)
 					};
 					debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id);
-					self.peerset.dropped(peer_id)
+					self.peerset.dropped(peer_id.clone())
 				},
 
 				// We can still get dial failures even if we are already connected to the node,
diff --git a/core/network-libp2p/src/service_task.rs b/core/network-libp2p/src/service_task.rs
index 37c4b05eaa..d9d65e6af8 100644
--- a/core/network-libp2p/src/service_task.rs
+++ b/core/network-libp2p/src/service_task.rs
@@ -38,7 +38,7 @@ use std::time::Duration;
 pub fn start_service<TMessage>(
 	config: NetworkConfiguration,
 	registered_custom: RegisteredProtocol<TMessage>,
-) -> Result<(Service<TMessage>, Arc<substrate_peerset::Peerset>), IoError>
+) -> Result<(Service<TMessage>, substrate_peerset::PeersetHandle), IoError>
 where TMessage: CustomMessage + Send + 'static {
 
 	if let Some(ref path) = config.net_config_path {
@@ -72,7 +72,7 @@ where TMessage: CustomMessage + Send + 'static {
 	}
 
 	// Build the peerset.
-	let (peerset, peerset_receiver) = substrate_peerset::Peerset::from_config(substrate_peerset::PeersetConfig {
+	let (peerset, peerset_handle) = substrate_peerset::Peerset::from_config(substrate_peerset::PeersetConfig {
 		in_peers: config.in_peers,
 		out_peers: config.out_peers,
 		bootnodes,
@@ -88,7 +88,7 @@ where TMessage: CustomMessage + Send + 'static {
 	// Build the swarm.
 	let (mut swarm, bandwidth) = {
 		let user_agent = format!("{} ({})", config.client_version, config.node_name);
-		let behaviour = Behaviour::new(user_agent, local_public, registered_custom, known_addresses, peerset_receiver, config.enable_mdns);
+		let behaviour = Behaviour::new(user_agent, local_public, registered_custom, known_addresses, peerset, config.enable_mdns);
 		let (transport, bandwidth) = transport::build_transport(local_identity);
 		(Swarm::new(transport, behaviour, local_peer_id.clone()), bandwidth)
 	};
@@ -116,7 +116,7 @@ where TMessage: CustomMessage + Send + 'static {
 		injected_events: Vec::new(),
 	};
 
-	Ok((service, peerset))
+	Ok((service, peerset_handle))
 }
 
 /// Event produced by the service.
diff --git a/core/network/src/service.rs b/core/network/src/service.rs
index 86701756c2..4fafd62d5f 100644
--- a/core/network/src/service.rs
+++ b/core/network/src/service.rs
@@ -24,7 +24,7 @@ use parking_lot::{Mutex, RwLock};
 use network_libp2p::{ProtocolId, NetworkConfiguration, Severity};
 use network_libp2p::{start_service, parse_str_addr, Service as NetworkService, ServiceEvent as NetworkServiceEvent};
 use network_libp2p::{multiaddr, RegisteredProtocol, NetworkState};
-use peerset::Peerset;
+use peerset::PeersetHandle;
 use consensus::import_queue::{ImportQueue, Link};
 use crate::consensus_gossip::ConsensusGossip;
 use crate::message::Message;
@@ -141,7 +141,7 @@ pub struct Service<B: BlockT + 'static, S: NetworkSpecialization<B>> {
 	network: Arc<Mutex<NetworkService<Message<B>>>>,
 	/// Peerset manager (PSM); manages the reputation of nodes and indicates the network which
 	/// nodes it should be connected to or not.
-	peerset: Arc<Peerset>,
+	peerset: PeersetHandle,
 	/// Protocol sender
 	protocol_sender: Sender<ProtocolMsg<B, S>>,
 	/// Sender for messages to the background service task, and handle for the background thread.
@@ -358,7 +358,7 @@ impl<B: BlockT + 'static, S: NetworkSpecialization<B>> ManageNetwork for Service
 	}
 
 	fn remove_reserved_peer(&self, peer: PeerId) {
-		self.peerset.remove_reserved_peer(&peer);
+		self.peerset.remove_reserved_peer(peer);
 	}
 
 	fn add_reserved_peer(&self, peer: String) -> Result<(), String> {
@@ -475,7 +475,7 @@ fn start_thread<B: BlockT + 'static>(
 	network_port: NetworkPort<B>,
 	config: NetworkConfiguration,
 	registered: RegisteredProtocol<Message<B>>,
-) -> Result<((oneshot::Sender<()>, thread::JoinHandle<()>), Arc<Mutex<NetworkService<Message<B>>>>, Arc<Peerset>), Error> {
+) -> Result<((oneshot::Sender<()>, thread::JoinHandle<()>), Arc<Mutex<NetworkService<Message<B>>>>, PeersetHandle), Error> {
 	// Start the main service.
 	let (service, peerset) = match start_service(config, registered) {
 		Ok((service, peerset)) => (Arc::new(Mutex::new(service)), peerset),
diff --git a/core/peerset/Cargo.toml b/core/peerset/Cargo.toml
index 12f27d84ef..1b505682d8 100644
--- a/core/peerset/Cargo.toml
+++ b/core/peerset/Cargo.toml
@@ -8,13 +8,9 @@ authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2018"
 
 [dependencies]
-fnv = "1.0"
 futures = "0.1"
 libp2p = { version = "0.6.0", default-features = false }
+linked-hash-map = "0.5"
 log = "0.4"
-parking_lot = "0.7"
-rand = "0.6"
-serde = "1.0.70"
-serde_derive = "1.0.70"
+lru-cache = "0.1.2"
 serde_json = "1.0.24"
-tokio-io = "0.1"
diff --git a/core/peerset/src/lib.rs b/core/peerset/src/lib.rs
index f49cbd6f12..9c6389a139 100644
--- a/core/peerset/src/lib.rs
+++ b/core/peerset/src/lib.rs
@@ -17,39 +17,138 @@
 //! Peer Set Manager (PSM). Contains the strategy for choosing which nodes the network should be
 //! connected to.
 
-use std::collections::HashSet;
-use futures::{prelude::*, sync::mpsc};
+mod slots;
+
+use std::collections::VecDeque;
+use futures::{prelude::*, sync::mpsc, try_ready};
 use libp2p::PeerId;
-use parking_lot::Mutex;
-use std::sync::Arc;
+use linked_hash_map::LinkedHashMap;
 use log::trace;
-
+use lru_cache::LruCache;
+use slots::{SlotType, SlotState, Slots};
 pub use serde_json::Value;
 
-/// Shared part of the peer set manager (PSM). Distributed around the code.
-pub struct Peerset {
-	tx: mpsc::UnboundedSender<Message>,
-	inner: Mutex<Inner>,
+const PEERSET_SCORES_CACHE_SIZE: usize = 1000;
+
+/// FIFO-ordered list of nodes that we know exist, but we are not connected to.
+#[derive(Debug, Default)]
+struct Discovered {
+	/// Nodes we should connect to first.
+	reserved: LinkedHashMap<PeerId, ()>,
+	/// All remaining nodes.
+	common: LinkedHashMap<PeerId, ()>,
+}
+
+impl Discovered {
+	/// Returns true if we already know given node.
+	fn contains(&self, peer_id: &PeerId) -> bool {
+		self.reserved.contains_key(peer_id) || self.common.contains_key(peer_id)
+	}
+
+	/// Returns true if given node is reserved.
+	fn is_reserved(&self, peer_id: &PeerId) -> bool {
+		self.reserved.contains_key(peer_id)
+	}
+
+	/// Adds new peer of a given type.
+	fn add_peer(&mut self, peer_id: PeerId, slot_type: SlotType) {
+		if !self.contains(&peer_id) {
+			match slot_type {
+				SlotType::Common => self.common.insert(peer_id, ()),
+				SlotType::Reserved => self.reserved.insert(peer_id, ()),
+			};
+		}
+	}
+
+	/// Pops the oldest peer from the list.
+	fn pop_peer(&mut self, reserved_only: bool) -> Option<(PeerId, SlotType)> {
+		if let Some((peer_id, _)) = self.reserved.pop_front() {
+			return Some((peer_id, SlotType::Reserved));
+		}
+
+		if reserved_only {
+			return None;
+		}
+
+		self.common.pop_front()
+			.map(|(peer_id, _)| (peer_id, SlotType::Common))
+	}
+
+	/// Marks the node as not reserved.
+	fn mark_not_reserved(&mut self, peer_id: &PeerId) {
+		if let Some(_) = self.reserved.remove(peer_id) {
+			self.common.insert(peer_id.clone(), ());
+		}
+	}
+
+	/// Removes the node from the list.
+	fn remove_peer(&mut self, peer_id: &PeerId) {
+		self.reserved.remove(peer_id);
+		self.common.remove(peer_id);
+	}
 }
 
-struct Inner {
-	/// List of nodes that we know exist but we are not connected to.
+#[derive(Debug)]
+struct PeersetData {
+	/// List of nodes that we know exist, but we are not connected to.
 	/// Elements in this list must never be in `out_slots` or `in_slots`.
-	discovered: Vec<PeerId>,
-	/// List of reserved nodes.
-	reserved: HashSet<PeerId>,
+	discovered: Discovered,
 	/// If true, we only accept reserved nodes.
 	reserved_only: bool,
-	/// Node slots for outgoing connections. Each slot contains either `None` if the node is free,
-	/// or `Some` if it is assigned to a peer.
-	out_slots: Vec<Option<PeerId>>,
-	/// Node slots for incoming connections. Each slot contains either `None` if the node is free,
-	/// or `Some` if it is assigned to a peer.
-	in_slots: Vec<Option<PeerId>>,
+	/// Node slots for outgoing connections.
+	out_slots: Slots,
+	/// Node slots for incoming connections.
+	in_slots: Slots,
+	/// List of node scores.
+	scores: LruCache<PeerId, i32>,
 }
 
-/// Message that can be sent by the peer set manager (PSM).
 #[derive(Debug)]
+enum Action {
+	AddReservedPeer(PeerId),
+	RemoveReservedPeer(PeerId),
+	SetReservedOnly(bool),
+	ReportPeer(PeerId, i32),
+}
+
+/// Shared handle to the peer set manager (PSM). Distributed around the code.
+#[derive(Debug, Clone)]
+pub struct PeersetHandle {
+	tx: mpsc::UnboundedSender<Action>,
+}
+
+impl PeersetHandle {
+	/// Adds a new reserved peer. The peerset will make an effort to always remain connected to
+	/// this peer.
+	///
+	/// Has no effect if the node was already a reserved peer.
+	///
+	/// > **Note**: Keep in mind that the networking has to know an address for this node,
+	/// >			otherwise it will not be able to connect to it.
+	pub fn add_reserved_peer(&self, peer_id: PeerId) {
+		let _ = self.tx.unbounded_send(Action::AddReservedPeer(peer_id));
+	}
+
+	/// Remove a previously-added reserved peer.
+	///
+	/// Has no effect if the node was not a reserved peer.
+	pub fn remove_reserved_peer(&self, peer_id: PeerId) {
+		let _ = self.tx.unbounded_send(Action::RemoveReservedPeer(peer_id));
+	}
+
+	/// Sets whether or not the peerset only has connections .
+	pub fn set_reserved_only(&self, reserved: bool) {
+		let _ = self.tx.unbounded_send(Action::SetReservedOnly(reserved));
+	}
+
+	/// Reports an adjustment to the reputation of the given peer.
+	pub fn report_peer(&self, peer_id: PeerId, score_diff: i32) {
+		let _ = self.tx.unbounded_send(Action::ReportPeer(peer_id, score_diff));
+	}
+}
+
+/// Message that can be sent by the peer set manager (PSM).
+#[derive(Debug, PartialEq)]
 pub enum Message {
 	/// Request to open a connection to the given peer. From the point of view of the PSM, we are
 	/// immediately connected.
@@ -104,130 +203,158 @@ pub struct PeersetConfig {
 ///
 /// Implements the `Stream` trait and can be polled for messages. The `Stream` never ends and never
 /// errors.
-pub struct PeersetMut {
-	parent: Arc<Peerset>,
-	rx: mpsc::UnboundedReceiver<Message>,
+#[derive(Debug)]
+pub struct Peerset {
+	data: PeersetData,
+	rx: mpsc::UnboundedReceiver<Action>,
+	message_queue: VecDeque<Message>,
 }
 
 impl Peerset {
 	/// Builds a new peerset from the given configuration.
-	pub fn from_config(config: PeersetConfig) -> (Arc<Peerset>, PeersetMut) {
+	pub fn from_config(config: PeersetConfig) -> (Peerset, PeersetHandle) {
 		let (tx, rx) = mpsc::unbounded();
 
-		let mut inner = Inner {
-			discovered: config.bootnodes.into_iter().collect(),
-			reserved: Default::default(),
+		let data = PeersetData {
+			discovered: Default::default(),
 			reserved_only: config.reserved_only,
-			out_slots: (0 .. config.out_peers).map(|_| None).collect(),
-			in_slots: (0 .. config.in_peers).map(|_| None).collect(),
+			out_slots: Slots::new(config.out_peers),
+			in_slots: Slots::new(config.in_peers),
+			scores: LruCache::new(PEERSET_SCORES_CACHE_SIZE),
 		};
 
-		alloc_slots(&mut inner, &tx);
-
-		let peerset = Arc::new(Peerset {
+		let handle = PeersetHandle {
 			tx,
-			inner: Mutex::new(inner),
-		});
+		};
 
-		let rx = PeersetMut {
-			parent: peerset.clone(),
+		let mut peerset = Peerset {
+			data,
 			rx,
+			message_queue: VecDeque::new(),
 		};
 
-		for reserved in config.reserved_nodes {
-			peerset.add_reserved_peer(reserved);
+		for peer_id in config.reserved_nodes {
+			peerset.data.discovered.add_peer(peer_id, SlotType::Reserved);
 		}
 
-		(peerset, rx)
-	}
-
-	/// Adds a new reserved peer. The peerset will make an effort to always remain connected to
-	/// this peer.
-	///
-	/// Has no effect if the node was already a reserved peer.
-	///
-	/// > **Note**: Keep in mind that the networking has to know an address for this node,
-	/// >			otherwise it will not be able to connect to it.
-	pub fn add_reserved_peer(&self, peer_id: PeerId) {
-		let mut inner = self.inner.lock();
-		if !inner.reserved.insert(peer_id.clone()) {
-			// Immediately return if this peer was already in the list.
-			return;
+		for peer_id in config.bootnodes {
+			peerset.data.discovered.add_peer(peer_id, SlotType::Common);
 		}
 
+		peerset.alloc_slots();
+		(peerset, handle)
+	}
+
+	fn on_add_reserved_peer(&mut self, peer_id: PeerId) {
 		// Nothing more to do if we're already connected.
-		if inner.out_slots.iter().chain(inner.in_slots.iter()).any(|s| s.as_ref() == Some(&peer_id)) {
+		if self.data.in_slots.contains(&peer_id) {
+			self.data.in_slots.mark_reserved(&peer_id);
 			return;
 		}
 
-		// Assign a slot for this reserved peer.
-		if let Some(pos) = inner.out_slots.iter().position(|s| s.as_ref().map(|n| !inner.reserved.contains(n)).unwrap_or(true)) {
-			let _ = self.tx.unbounded_send(Message::Connect(peer_id.clone()));
-			inner.out_slots[pos] = Some(peer_id);
-
-		} else {
-			// All slots are filled with reserved peers.
-			if inner.discovered.iter().all(|p| *p != peer_id) {
-				inner.discovered.push(peer_id);
+		match self.data.out_slots.add_peer(peer_id, SlotType::Reserved) {
+			SlotState::Added(peer_id) => {
+				// reserved node may have been previously stored as normal node in discovered list
+				self.data.discovered.remove_peer(&peer_id);
+
+				// notify that connection has been made
+				self.message_queue.push_back(Message::Connect(peer_id));
+				return;
+			},
+			SlotState::Swaped { removed, added } => {
+				// reserved node may have been previously stored as normal node in discovered list
+				self.data.discovered.remove_peer(&added);
+				// let's add the peer we disconnected from to the discovered list again
+				self.data.discovered.add_peer(removed.clone(), SlotType::Common);
+				// swap connections
+				self.message_queue.push_back(Message::Drop(removed));
+				self.message_queue.push_back(Message::Connect(added));
+			}
+			SlotState::AlreadyConnected(_) | SlotState::Upgraded(_) => {
+				return;
+			}
+			SlotState::MaxConnections(peer_id) => {
+				self.data.discovered.add_peer(peer_id, SlotType::Reserved);
+				return;
 			}
 		}
 	}
 
-	/// Remove a previously-added reserved peer.
-	///
-	/// Has no effect if the node was not a reserved peer.
-	pub fn remove_reserved_peer(&self, peer_id: &PeerId) {
-		let mut inner = self.inner.lock();
-		inner.reserved.remove(peer_id);
+	fn on_remove_reserved_peer(&mut self, peer_id: PeerId) {
+		self.data.in_slots.mark_not_reserved(&peer_id);
+		self.data.out_slots.mark_not_reserved(&peer_id);
+		self.data.discovered.mark_not_reserved(&peer_id);
+		if self.data.reserved_only {
+			if self.data.in_slots.clear_slot(&peer_id) || self.data.out_slots.clear_slot(&peer_id) {
+				// insert peer back into discovered list
+				self.data.discovered.add_peer(peer_id.clone(), SlotType::Common);
+				self.message_queue.push_back(Message::Drop(peer_id));
+				// call alloc_slots again, cause we may have some reserved peers in discovered list
+				// waiting for the slot that was just cleared
+				self.alloc_slots();
+			}
+		}
 	}
 
-	/// Sets whether or not the peerset only has connections .
-	pub fn set_reserved_only(&self, reserved_only: bool) {
-		let mut inner = self.inner.lock();
-		let inner = &mut *inner;	// Fixes a borrowing issue.
-		inner.reserved_only = reserved_only;
-
+	fn on_set_reserved_only(&mut self, reserved_only: bool) {
 		// Disconnect non-reserved nodes.
-		if reserved_only {
-			for slot in inner.out_slots.iter_mut().chain(inner.in_slots.iter_mut()) {
-				if let Some(peer) = slot.as_ref() {
-					if inner.reserved.contains(peer) {
-						continue;
-					}
-
-					let _ = self.tx.unbounded_send(Message::Drop(peer.clone()));
-				}
-
-				*slot = None;
+		self.data.reserved_only = reserved_only;
+		if self.data.reserved_only {
+			for peer_id in self.data.in_slots.clear_common_slots().into_iter().chain(self.data.out_slots.clear_common_slots().into_iter()) {
+				// insert peer back into discovered list
+				self.data.discovered.add_peer(peer_id.clone(), SlotType::Common);
+				self.message_queue.push_back(Message::Drop(peer_id));
 			}
+		} else {
+			self.alloc_slots();
 		}
 	}
 
-	/// Reports an adjustement to the reputation of the given peer.
-	pub fn report_peer(&self, _peer_id: &PeerId, _score_diff: i32) {
-		// This is not implemented in this dummy implementation.
-	}
-}
-
-fn alloc_slots(inner: &mut Inner, tx: &mpsc::UnboundedSender<Message>) {
-	if inner.reserved_only {
-		return;
-	}
+	fn on_report_peer(&mut self, peer_id: PeerId, score_diff: i32) {
+		let score = match self.data.scores.get_mut(&peer_id) {
+			Some(score) => {
+				*score = score.saturating_add(score_diff);
+				*score
+			},
+			None => {
+				self.data.scores.insert(peer_id.clone(), score_diff);
+				score_diff
+			}
+		};
 
-	for slot in inner.out_slots.iter_mut() {
-		if slot.is_some() {
-			continue;
+		if score < 0 {
+			// peer will be removed from `in_slots` or `out_slots` in `on_dropped` method
+			if self.data.in_slots.contains(&peer_id) || self.data.out_slots.contains(&peer_id) {
+				self.data.in_slots.clear_slot(&peer_id);
+				self.data.out_slots.clear_slot(&peer_id);
+				self.message_queue.push_back(Message::Drop(peer_id));
+			}
 		}
+	}
 
-		if !inner.discovered.is_empty() {
-			let elem = inner.discovered.remove(0);
-			*slot = Some(elem.clone());
-			let _ = tx.unbounded_send(Message::Connect(elem));
+	fn alloc_slots(&mut self) {
+		while let Some((peer_id, slot_type)) = self.data.discovered.pop_peer(self.data.reserved_only) {
+			match self.data.out_slots.add_peer(peer_id, slot_type) {
+				SlotState::Added(peer_id) => {
+					self.message_queue.push_back(Message::Connect(peer_id));
+				},
+				SlotState::Swaped { removed, added } => {
+					// insert peer back into discovered list
+					self.data.discovered.add_peer(removed.clone(), SlotType::Common);
+					self.message_queue.push_back(Message::Drop(removed));
+					self.message_queue.push_back(Message::Connect(added));
+				}
+				SlotState::Upgraded(_) | SlotState::AlreadyConnected(_) => {
+					// TODO: we should never reach this point
+				},
+				SlotState::MaxConnections(peer_id) => {
+					self.data.discovered.add_peer(peer_id, slot_type);
+					break;
+				},
+			}
 		}
 	}
-}
 
-impl PeersetMut {
 	/// Indicate that we received an incoming connection. Must be answered either with
 	/// a corresponding `Accept` or `Reject`, except if we were already connected to this peer.
 	///
@@ -237,21 +364,51 @@ impl PeersetMut {
 	///
 	/// Because of concurrency issues, it is acceptable to call `incoming` with a `PeerId` the
 	/// peerset is already connected to, in which case it must not answer.
-	pub fn incoming(&self, peer_id: PeerId, index: IncomingIndex) {
-		let mut inner = self.parent.inner.lock();
-		trace!("Incoming {}\nin_slots={:?}\nout_slots={:?}", peer_id, inner.in_slots, inner.out_slots);
-		if inner.out_slots.iter().chain(inner.in_slots.iter()).any(|s| s.as_ref() == Some(&peer_id)) {
-			return
+	pub fn incoming(&mut self, peer_id: PeerId, index: IncomingIndex) {
+		trace!("Incoming {}\nin_slots={:?}\nout_slots={:?}", peer_id, self.data.in_slots, self.data.out_slots);
+		// if `reserved_only` is set, but this peer is not a part of our discovered list,
+		// a) it is not reserved, so we reject the connection
+		// b) we are already connected to it, so we reject the connection
+		if self.data.reserved_only && !self.data.discovered.is_reserved(&peer_id) {
+			self.message_queue.push_back(Message::Reject(index));
+			return;
+		}
+
+		// check if we are already connected to this peer
+		if self.data.out_slots.contains(&peer_id) {
+			// we are already connected. in this case we do not answer
+			return;
 		}
 
-		if let Some(pos) = inner.in_slots.iter().position(|s| s.is_none()) {
-			inner.in_slots[pos] = Some(peer_id);
-			let _ = self.parent.tx.unbounded_send(Message::Accept(index));
+		let slot_type = if self.data.reserved_only {
+			SlotType::Reserved
 		} else {
-			if inner.discovered.iter().all(|p| *p != peer_id) {
-				inner.discovered.push(peer_id);
-			}
-			let _ = self.parent.tx.unbounded_send(Message::Reject(index));
+			SlotType::Common
+		};
+
+		match self.data.in_slots.add_peer(peer_id, slot_type) {
+			SlotState::Added(peer_id) => {
+				// reserved node may have been previously stored as normal node in discovered list
+				self.data.discovered.remove_peer(&peer_id);
+				self.message_queue.push_back(Message::Accept(index));
+				return;
+			},
+			SlotState::Swaped { removed, added } => {
+				// reserved node may have been previously stored as normal node in discovered list
+				self.data.discovered.remove_peer(&added);
+				// swap connections.
+				self.message_queue.push_back(Message::Drop(removed));
+				self.message_queue.push_back(Message::Accept(index));
+			},
+			SlotState::AlreadyConnected(_) | SlotState::Upgraded(_) => {
+				// we are already connected. in this case we do not answer
+				return;
+			},
+			SlotState::MaxConnections(peer_id) => {
+				self.data.discovered.add_peer(peer_id, slot_type);
+				self.message_queue.push_back(Message::Reject(index));
+				return;
+			},
 		}
 	}
 
@@ -259,48 +416,35 @@ impl PeersetMut {
 	///
 	/// Must only be called after the PSM has either generated a `Connect` message with this
 	/// `PeerId`, or accepted an incoming connection with this `PeerId`.
-	pub fn dropped(&self, peer_id: &PeerId) {
-		let mut inner = self.parent.inner.lock();
-		let inner = &mut *inner;	// Fixes a borrowing issue.
-		trace!("Dropping {}\nin_slots={:?}\nout_slots={:?}", peer_id, inner.in_slots, inner.out_slots);
-
+	pub fn dropped(&mut self, peer_id: PeerId) {
+		trace!("Dropping {}\nin_slots={:?}\nout_slots={:?}", peer_id, self.data.in_slots, self.data.out_slots);
 		// Automatically connect back if reserved.
-		if inner.reserved.contains(peer_id) {
-			let _ = self.parent.tx.unbounded_send(Message::Connect(peer_id.clone()));
-			return
+		if self.data.in_slots.is_connected_and_reserved(&peer_id) || self.data.out_slots.is_connected_and_reserved(&peer_id) {
+			self.message_queue.push_back(Message::Connect(peer_id));
+			return;
 		}
 
 		// Otherwise, free the slot.
-		for slot in inner.out_slots.iter_mut().chain(inner.in_slots.iter_mut()) {
-			if slot.as_ref() == Some(peer_id) {
-				*slot = None;
-				break;
-			}
-		}
+		self.data.in_slots.clear_slot(&peer_id);
+		self.data.out_slots.clear_slot(&peer_id);
 
 		// Note: in this dummy implementation we consider that peers never expire. As soon as we
 		// are disconnected from a peer, we try again.
-		if inner.discovered.iter().all(|p| p != peer_id) {
-			inner.discovered.push(peer_id.clone());
-		}
-		alloc_slots(inner, &self.parent.tx);
+		self.data.discovered.add_peer(peer_id, SlotType::Common);
+		self.alloc_slots();
 	}
 
 	/// Adds a discovered peer id to the PSM.
 	///
 	/// > **Note**: There is no equivalent "expired" message, meaning that it is the responsibility
 	/// >			of the PSM to remove `PeerId`s that fail to dial too often.
-	pub fn discovered(&self, peer_id: PeerId) {
-		let mut inner = self.parent.inner.lock();
-
-		if inner.out_slots.iter().chain(inner.in_slots.iter()).any(|p| p.as_ref() == Some(&peer_id)) {
+	pub fn discovered(&mut self, peer_id: PeerId) {
+		if self.data.in_slots.contains(&peer_id) || self.data.out_slots.contains(&peer_id) {
 			return;
 		}
 
-		if inner.discovered.iter().all(|p| *p != peer_id) {
-			inner.discovered.push(peer_id);
-		}
-		alloc_slots(&mut inner, &self.parent.tx);
+		self.data.discovered.add_peer(peer_id, SlotType::Common);
+		self.alloc_slots();
 	}
 
 	/// Produces a JSON object containing the state of the peerset manager, for debugging purposes.
@@ -309,11 +453,281 @@ impl PeersetMut {
 	}
 }
 
-impl Stream for PeersetMut {
+impl Stream for Peerset {
 	type Item = Message;
 	type Error = ();
 
 	fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
-		self.rx.poll()
+		loop {
+			if let Some(message) = self.message_queue.pop_front() {
+				return Ok(Async::Ready(Some(message)));
+			}
+			match try_ready!(self.rx.poll()) {
+				None => return Ok(Async::Ready(None)),
+				Some(action) => match action {
+					Action::AddReservedPeer(peer_id) => self.on_add_reserved_peer(peer_id),
+					Action::RemoveReservedPeer(peer_id) => self.on_remove_reserved_peer(peer_id),
+					Action::SetReservedOnly(reserved) => self.on_set_reserved_only(reserved),
+					Action::ReportPeer(peer_id, score_diff) => self.on_report_peer(peer_id, score_diff),
+				}
+			}
+		}
+	}
+}
+
+#[cfg(test)]
+mod tests {
+	use libp2p::PeerId;
+	use futures::prelude::*;
+	use super::{PeersetConfig, Peerset, Message, IncomingIndex};
+
+	fn assert_messages(mut peerset: Peerset, messages: Vec<Message>) -> Peerset {
+		for expected_message in messages {
+			let (message, p) = next_message(peerset).expect("expected message");
+			assert_eq!(message, expected_message);
+			peerset = p;
+		}
+		assert!(peerset.message_queue.is_empty());
+		peerset
+	}
+
+	fn next_message(peerset: Peerset) -> Result<(Message, Peerset), ()> {
+		let (next, peerset) = peerset.into_future()
+			.wait()
+			.map_err(|_| ())?;
+		let message = next.ok_or_else(|| ())?;
+		Ok((message, peerset))
+	}
+
+	#[test]
+	fn test_peerset_from_config_with_bootnodes() {
+		let bootnode = PeerId::random();
+		let bootnode2 = PeerId::random();
+		let config = PeersetConfig {
+			in_peers: 0,
+			out_peers: 2,
+			bootnodes: vec![bootnode.clone(), bootnode2.clone()],
+			reserved_only: false,
+			reserved_nodes: Vec::new(),
+		};
+
+		let (peerset, _handle) = Peerset::from_config(config);
+
+		assert_messages(peerset, vec![
+			Message::Connect(bootnode),
+			Message::Connect(bootnode2),
+		]);
+	}
+
+	#[test]
+	fn test_peerset_from_config_with_reserved_nodes() {
+		let bootnode = PeerId::random();
+		let bootnode2 = PeerId::random();
+		let reserved_peer = PeerId::random();
+		let reserved_peer2 = PeerId::random();
+		let config = PeersetConfig {
+			in_peers: 0,
+			out_peers: 3,
+			bootnodes: vec![bootnode.clone(), bootnode2.clone()],
+			reserved_only: false,
+			reserved_nodes: vec![reserved_peer.clone(), reserved_peer2.clone()],
+		};
+
+		let (peerset, _handle) = Peerset::from_config(config);
+
+		assert_messages(peerset, vec![
+			Message::Connect(reserved_peer),
+			Message::Connect(reserved_peer2),
+			Message::Connect(bootnode)
+		]);
+	}
+
+	#[test]
+	fn test_peerset_add_reserved_peer() {
+		let bootnode = PeerId::random();
+		let reserved_peer = PeerId::random();
+		let reserved_peer2 = PeerId::random();
+		let config = PeersetConfig {
+			in_peers: 0,
+			out_peers: 2,
+			bootnodes: vec![bootnode],
+			reserved_only: true,
+			reserved_nodes: Vec::new(),
+		};
+
+		let (peerset, handle) = Peerset::from_config(config);
+		handle.add_reserved_peer(reserved_peer.clone());
+		handle.add_reserved_peer(reserved_peer2.clone());
+
+		assert_messages(peerset, vec![
+			Message::Connect(reserved_peer),
+			Message::Connect(reserved_peer2)
+		]);
+	}
+
+	#[test]
+	fn test_peerset_remove_reserved_peer() {
+		let reserved_peer = PeerId::random();
+		let reserved_peer2 = PeerId::random();
+		let config = PeersetConfig {
+			in_peers: 0,
+			out_peers: 2,
+			bootnodes: vec![],
+			reserved_only: false,
+			reserved_nodes: vec![reserved_peer.clone(), reserved_peer2.clone()],
+		};
+
+		let (peerset, handle) = Peerset::from_config(config);
+		handle.remove_reserved_peer(reserved_peer.clone());
+
+		let peerset = assert_messages(peerset, vec![
+			Message::Connect(reserved_peer.clone()),
+			Message::Connect(reserved_peer2.clone()),
+		]);
+
+		handle.set_reserved_only(true);
+		handle.remove_reserved_peer(reserved_peer2.clone());
+
+		assert_messages(peerset, vec![
+			Message::Drop(reserved_peer),
+			Message::Drop(reserved_peer2),
+		]);
+	}
+
+	#[test]
+	fn test_peerset_set_reserved_only() {
+		let bootnode = PeerId::random();
+		let bootnode2 = PeerId::random();
+		let reserved_peer = PeerId::random();
+		let reserved_peer2 = PeerId::random();
+		let config = PeersetConfig {
+			in_peers: 0,
+			out_peers: 4,
+			bootnodes: vec![bootnode.clone(), bootnode2.clone()],
+			reserved_only: false,
+			reserved_nodes: vec![reserved_peer.clone(), reserved_peer2.clone()],
+		};
+
+		let (peerset, handle) = Peerset::from_config(config);
+		handle.set_reserved_only(true);
+		handle.set_reserved_only(false);
+
+		assert_messages(peerset, vec![
+			Message::Connect(reserved_peer),
+			Message::Connect(reserved_peer2),
+			Message::Connect(bootnode.clone()),
+			Message::Connect(bootnode2.clone()),
+			Message::Drop(bootnode.clone()),
+			Message::Drop(bootnode2.clone()),
+			Message::Connect(bootnode),
+			Message::Connect(bootnode2),
+		]);
+	}
+
+	#[test]
+	fn test_peerset_report_peer() {
+		let bootnode = PeerId::random();
+		let bootnode2 = PeerId::random();
+		let config = PeersetConfig {
+			in_peers: 0,
+			out_peers: 1,
+			bootnodes: vec![bootnode.clone(), bootnode2.clone()],
+			reserved_only: false,
+			reserved_nodes: Vec::new(),
+		};
+
+		let (peerset, handle) = Peerset::from_config(config);
+		handle.report_peer(bootnode2, -1);
+		handle.report_peer(bootnode.clone(), -1);
+
+		assert_messages(peerset, vec![
+			Message::Connect(bootnode.clone()),
+			Message::Drop(bootnode)
+		]);
+	}
+
+	#[test]
+	fn test_peerset_incoming() {
+		let bootnode = PeerId::random();
+		let incoming = PeerId::random();
+		let incoming2 = PeerId::random();
+		let incoming3 = PeerId::random();
+		let ii = IncomingIndex(1);
+		let ii2 = IncomingIndex(2);
+		let ii3 = IncomingIndex(3);
+		let ii4 = IncomingIndex(3);
+		let config = PeersetConfig {
+			in_peers: 2,
+			out_peers: 1,
+			bootnodes: vec![bootnode.clone()],
+			reserved_only: false,
+			reserved_nodes: Vec::new(),
+		};
+
+		let (mut peerset, _handle) = Peerset::from_config(config);
+		peerset.incoming(incoming.clone(), ii);
+		peerset.incoming(incoming.clone(), ii4);
+		peerset.incoming(incoming2.clone(), ii2);
+		peerset.incoming(incoming3.clone(), ii3);
+
+		assert_messages(peerset, vec![
+			Message::Connect(bootnode.clone()),
+			Message::Accept(ii),
+			Message::Accept(ii2),
+			Message::Reject(ii3),
+		]);
+	}
+
+	#[test]
+	fn test_peerset_dropped() {
+		let bootnode = PeerId::random();
+		let bootnode2 = PeerId::random();
+		let reserved_peer = PeerId::random();
+		let config = PeersetConfig {
+			in_peers: 0,
+			out_peers: 2,
+			bootnodes: vec![bootnode.clone(), bootnode2.clone()],
+			reserved_only: false,
+			reserved_nodes: vec![reserved_peer.clone()],
+		};
+
+		let (peerset, _handle) = Peerset::from_config(config);
+
+		let mut peerset = assert_messages(peerset, vec![
+			Message::Connect(reserved_peer.clone()),
+			Message::Connect(bootnode.clone()),
+		]);
+
+		peerset.dropped(reserved_peer.clone());
+		peerset.dropped(bootnode);
+
+		let _peerset = assert_messages(peerset, vec![
+			Message::Connect(reserved_peer),
+			Message::Connect(bootnode2),
+		]);
+	}
+
+	#[test]
+	fn test_peerset_discovered() {
+		let bootnode = PeerId::random();
+		let discovered = PeerId::random();
+		let discovered2 = PeerId::random();
+		let config = PeersetConfig {
+			in_peers: 0,
+			out_peers: 2,
+			bootnodes: vec![bootnode.clone()],
+			reserved_only: false,
+			reserved_nodes: vec![],
+		};
+
+		let (mut peerset, _handle) = Peerset::from_config(config);
+		peerset.discovered(discovered.clone());
+		peerset.discovered(discovered.clone());
+		peerset.discovered(discovered2);
+
+		assert_messages(peerset, vec![
+			Message::Connect(bootnode),
+			Message::Connect(discovered),
+		]);
 	}
 }
diff --git a/core/peerset/src/slots.rs b/core/peerset/src/slots.rs
new file mode 100644
index 0000000000..7fa655d7ff
--- /dev/null
+++ b/core/peerset/src/slots.rs
@@ -0,0 +1,148 @@
+// Copyright 2018-2019 Parity Technologies (UK) Ltd.
+// This file is part of Substrate.
+
+// Substrate is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Substrate is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
+
+use std::mem;
+use libp2p::PeerId;
+use linked_hash_map::LinkedHashMap;
+
+/// Describes the nature of connection with a given peer.
+#[derive(Debug, PartialEq, Clone, Copy)]
+pub enum SlotType {
+	/// Reserved peer is a peer we should always stay connected to.
+	Reserved,
+	/// Common peer is a type of peer that we stay connected to only if it's
+	/// useful for us.
+	Common,
+}
+
+/// Descibes the result of `add_peer` action.
+pub enum SlotState {
+	/// Returned when `add_peer` successfully adds a peer to the slot.
+	Added(PeerId),
+	/// Returned we already have a connection to a given peer, but it is upgraded from
+	/// `Common` to `Reserved`.
+	Upgraded(PeerId),
+	/// Returned when we should removed a common peer to make space for a reserved peer.
+	Swaped {
+		/// Peer we should disconnect from.
+		removed: PeerId,
+		/// Peer we should connect to.
+		added: PeerId,
+	},
+	/// Error returned when we are already connected to this peer.
+	AlreadyConnected(PeerId),
+	/// Error returned when max number of connections has been already established.
+	MaxConnections(PeerId),
+}
+
+/// Contains all information about group of slots.
+#[derive(Debug)]
+pub struct Slots {
+	max_slots: usize,
+	/// Nodes and their type. We use `LinkedHashMap` to make this data structure more predictable
+	slots: LinkedHashMap<PeerId, SlotType>,
+}
+
+impl Slots {
+	/// Creates a group of slots with a limited size.
+	pub fn new(max_slots: u32) -> Self {
+		let max_slots = max_slots as usize;
+		Slots {
+			max_slots,
+			slots: LinkedHashMap::with_capacity(max_slots),
+		}
+	}
+
+	/// Returns true if one of the slots contains given peer.
+	pub fn contains(&self, peer_id: &PeerId) -> bool {
+		self.slots.contains_key(peer_id)
+	}
+
+	/// Tries to find a slot for a given peer and returns `SlotState`.
+	pub fn add_peer(&mut self, peer_id: PeerId, slot_type: SlotType) -> SlotState {
+		if let Some(st) = self.slots.get_mut(&peer_id) {
+			if *st == SlotType::Common && slot_type == SlotType::Reserved {
+				*st = SlotType::Reserved;
+				return SlotState::Upgraded(peer_id);
+			} else {
+				return SlotState::AlreadyConnected(peer_id);
+			}
+		}
+
+		if self.slots.len() == self.max_slots {
+			if let SlotType::Reserved = slot_type {
+				// if we are trying to insert a reserved peer, but we all of our slots are full,
+				// we need to remove one of the existing common connections
+				let to_remove = self.slots.iter()
+					.find(|(_, &slot_type)| slot_type == SlotType::Common)
+					.map(|(to_remove, _)| to_remove)
+					.cloned();
+
+				if let Some(to_remove) = to_remove {
+					self.slots.remove(&to_remove);
+					self.slots.insert(peer_id.clone(), slot_type);
+
+					return SlotState::Swaped {
+						removed: to_remove,
+						added: peer_id,
+					};
+				}
+			}
+			return SlotState::MaxConnections(peer_id);
+		}
+
+		self.slots.insert(peer_id.clone(), slot_type);
+		SlotState::Added(peer_id)
+	}
+
+	pub fn clear_common_slots(&mut self) -> Vec<PeerId> {
+		let slots = mem::replace(&mut self.slots, LinkedHashMap::with_capacity(self.max_slots));
+		let mut common_peers = Vec::new();
+		for (peer_id, slot_type) in slots {
+			match slot_type {
+				SlotType::Common => {
+					common_peers.push(peer_id);
+				},
+				SlotType::Reserved => {
+					self.slots.insert(peer_id, slot_type);
+				},
+			}
+		}
+		common_peers
+	}
+
+	pub fn mark_reserved(&mut self, peer_id: &PeerId) {
+		if let Some(slot_type) = self.slots.get_mut(peer_id) {
+			*slot_type = SlotType::Reserved;
+		}
+	}
+
+	pub fn mark_not_reserved(&mut self, peer_id: &PeerId) {
+		if let Some(slot_type) = self.slots.get_mut(peer_id) {
+			*slot_type = SlotType::Common;
+		}
+	}
+
+	pub fn clear_slot(&mut self, peer_id: &PeerId) -> bool {
+		self.slots.remove(peer_id).is_some()
+	}
+
+	pub fn is_connected_and_reserved(&self, peer_id: &PeerId) -> bool {
+		self.slots.get(peer_id)
+			.map(|slot_type| *slot_type == SlotType::Reserved)
+			.unwrap_or_else(|| false)
+	}
+}
-- 
GitLab