diff --git a/Cargo.lock b/Cargo.lock
index 596c320601a..2aaf3f89f36 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1614,6 +1614,19 @@ dependencies = [
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "node-filter"
+version = "1.8.0"
+dependencies = [
+ "ethcore 1.8.0",
+ "ethcore-io 1.8.0",
+ "ethcore-network 1.8.0",
+ "ethcore-util 1.8.0",
+ "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "native-contracts 0.1.0",
+]
+
[[package]]
name = "node-health"
version = "0.1.0"
@@ -1837,6 +1850,7 @@ dependencies = [
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "node-filter 1.8.0",
"node-health 0.1.0",
"num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/Cargo.toml b/Cargo.toml
index ebd60ca64cc..06abd7b3169 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -42,6 +42,7 @@ ethcore-light = { path = "ethcore/light" }
ethcore-logger = { path = "logger" }
ethcore-stratum = { path = "stratum" }
ethcore-network = { path = "util/network" }
+node-filter = { path = "ethcore/node_filter" }
ethkey = { path = "ethkey" }
node-health = { path = "dapps/node-health" }
rlp = { path = "util/rlp" }
diff --git a/ethcore/native_contracts/build.rs b/ethcore/native_contracts/build.rs
index bcb64067c28..e7985b3880b 100644
--- a/ethcore/native_contracts/build.rs
+++ b/ethcore/native_contracts/build.rs
@@ -28,6 +28,7 @@ const SERVICE_TRANSACTION_ABI: &'static str = include_str!("res/service_transact
const SECRETSTORE_ACL_STORAGE_ABI: &'static str = include_str!("res/secretstore_acl_storage.json");
const VALIDATOR_SET_ABI: &'static str = include_str!("res/validator_set.json");
const VALIDATOR_REPORT_ABI: &'static str = include_str!("res/validator_report.json");
+const PEER_SET_ABI: &'static str = include_str!("res/peer_set.json");
const TEST_VALIDATOR_SET_ABI: &'static str = include_str!("res/test_validator_set.json");
@@ -53,6 +54,7 @@ fn main() {
build_file("SecretStoreAclStorage", SECRETSTORE_ACL_STORAGE_ABI, "secretstore_acl_storage.rs");
build_file("ValidatorSet", VALIDATOR_SET_ABI, "validator_set.rs");
build_file("ValidatorReport", VALIDATOR_REPORT_ABI, "validator_report.rs");
+ build_file("PeerSet", PEER_SET_ABI, "peer_set.rs");
build_test_contracts();
}
diff --git a/ethcore/native_contracts/res/peer_set.json b/ethcore/native_contracts/res/peer_set.json
new file mode 100644
index 00000000000..a932f948d0a
--- /dev/null
+++ b/ethcore/native_contracts/res/peer_set.json
@@ -0,0 +1 @@
+[{"constant":true,"inputs":[{"name":"sl","type":"bytes32"},{"name":"sh","type":"bytes32"},{"name":"pl","type":"bytes32"},{"name":"ph","type":"bytes32"}],"name":"connectionAllowed","outputs":[{"name":"res","type":"bool"}],"payable":false,"type":"function"},{"inputs":[],"payable":false,"type":"constructor"}]
diff --git a/ethcore/native_contracts/src/lib.rs b/ethcore/native_contracts/src/lib.rs
index 58875f8a2f1..733dea80e6a 100644
--- a/ethcore/native_contracts/src/lib.rs
+++ b/ethcore/native_contracts/src/lib.rs
@@ -30,6 +30,7 @@ mod service_transaction;
mod secretstore_acl_storage;
mod validator_set;
mod validator_report;
+mod peer_set;
pub mod test_contracts;
@@ -40,3 +41,4 @@ pub use self::service_transaction::ServiceTransactionChecker;
pub use self::secretstore_acl_storage::SecretStoreAclStorage;
pub use self::validator_set::ValidatorSet;
pub use self::validator_report::ValidatorReport;
+pub use self::peer_set::PeerSet;
diff --git a/ethcore/native_contracts/src/peer_set.rs b/ethcore/native_contracts/src/peer_set.rs
new file mode 100644
index 00000000000..09d0ecbb8d1
--- /dev/null
+++ b/ethcore/native_contracts/src/peer_set.rs
@@ -0,0 +1,21 @@
+// Copyright 2015-2017 Parity Technologies (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+#![allow(unused_mut, unused_variables, unused_imports)]
+
+//! Peer set contract.
+
+include!(concat!(env!("OUT_DIR"), "/peer_set.rs"));
diff --git a/ethcore/node_filter/Cargo.toml b/ethcore/node_filter/Cargo.toml
new file mode 100644
index 00000000000..e885ef1d105
--- /dev/null
+++ b/ethcore/node_filter/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+description = "Parity smart network connections"
+homepage = "http://parity.io"
+license = "GPL-3.0"
+name = "node-filter"
+version = "1.8.0"
+authors = ["Parity Technologies "]
+
+[dependencies]
+ethcore = { path = ".."}
+ethcore-util = { path = "../../util" }
+ethcore-io = { path = "../../util/io" }
+ethcore-network = { path = "../../util/network" }
+native-contracts = { path = "../native_contracts" }
+futures = "0.1"
+log = "0.3"
diff --git a/ethcore/node_filter/res/node_filter.json b/ethcore/node_filter/res/node_filter.json
new file mode 100644
index 00000000000..f8eb1715296
--- /dev/null
+++ b/ethcore/node_filter/res/node_filter.json
@@ -0,0 +1,44 @@
+{
+ "name": "TestNodeFilterContract",
+ "engine": {
+ "authorityRound": {
+ "params": {
+ "stepDuration": 1,
+ "startStep": 2,
+ "validators": {
+ "contract": "0x0000000000000000000000000000000000000005"
+ }
+ }
+ }
+ },
+ "params": {
+ "accountStartNonce": "0x0",
+ "maximumExtraDataSize": "0x20",
+ "minGasLimit": "0x1388",
+ "networkID" : "0x69",
+ "gasLimitBoundDivisor": "0x0400"
+ },
+ "genesis": {
+ "seal": {
+ "generic": "0xc180"
+ },
+ "difficulty": "0x20000",
+ "author": "0x0000000000000000000000000000000000000000",
+ "timestamp": "0x00",
+ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "extraData": "0x",
+ "gasLimit": "0x222222"
+ },
+ "accounts": {
+ "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
+ "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
+ "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
+ "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
+ "0000000000000000000000000000000000000005": {
+ "balance": "1",
+ "constructor": "6060604052341561000f57600080fd5b5b6012600102600080601160010260001916815260200190815260200160002081600019169055506022600102600080602160010260001916815260200190815260200160002081600019169055506032600102600080603160010260001916815260200190815260200160002081600019169055506042600102600080604160010260001916815260200190815260200160002081600019169055505b5b610155806100bd6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063994d790a1461003e575b600080fd5b341561004957600080fd5b61008a6004808035600019169060200190919080356000191690602001909190803560001916906020019091908035600019169060200190919050506100a4565b604051808215151515815260200191505060405180910390f35b60006001800285600019161480156100c3575060026001028460001916145b156100d15760019050610121565b60006001028360001916141580156100f157506000600102826000191614155b801561011e5750816000191660008085600019166000191681526020019081526020016000205460001916145b90505b9493505050505600a165627a7a723058202082b8d8667fd397925f39785d8e804540beda0524d28af15921375145dfcc250029"
+ },
+ "0x7d577a597b2742b498cb5cf0c26cdcd726d39e6e": { "balance": "1606938044258990275541962092341162602522202993782792835301376" },
+ "0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }
+ }
+}
diff --git a/ethcore/node_filter/src/lib.rs b/ethcore/node_filter/src/lib.rs
new file mode 100644
index 00000000000..d3dcbaa3be0
--- /dev/null
+++ b/ethcore/node_filter/src/lib.rs
@@ -0,0 +1,154 @@
+// Copyright 2015-2017 Parity Technologies (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+//! Smart contract based node filter.
+
+extern crate ethcore;
+extern crate ethcore_util as util;
+extern crate ethcore_network as network;
+extern crate native_contracts;
+extern crate futures;
+#[cfg(test)] extern crate ethcore_io as io;
+#[macro_use] extern crate log;
+
+use std::sync::Weak;
+use std::collections::HashMap;
+use native_contracts::PeerSet as Contract;
+use network::{NodeId, ConnectionFilter, ConnectionDirection};
+use ethcore::client::{BlockChainClient, BlockId, ChainNotify};
+use util::{Mutex, Address, H256, Bytes};
+use futures::Future;
+
+const MAX_CACHE_SIZE: usize = 4096;
+
+/// Connection filter that uses a contract to manage permissions.
+pub struct NodeFilter {
+ contract: Mutex