Introduce flag to enable sentry nodes to participate in grandpa gossip (#3018)

Given the following situation: A validator 'A' is not supposed to be
connected to the public internet to protect it from e.g. a DoS attack.
Instead it connects to a sentry node 'sentry-A' which connects to the
public internet. Validator 'B' can reach validator 'A' via sentry node
'sentry-A' and vice versa.

A sentry node needs to participate in the grandpa gossip without
becoming a validator itself in order to forward these message to its
validator. This commit adds a new command line flag (`--grandpa-voter`)
forcing a node to participate in the grandpa voting process even though
no `--key` was specified. Due to the fact that it does not have a key,
it does not become a validator in the network.

In order to simulate the above situation this commit also adds a Docker
Compose file (`scripts/sentry-node/docker-compose.yml`) with further
documentation.
This commit is contained in:
Max Inden
2019-07-09 18:35:37 +02:00
committed by Gavin Wood
parent 2c5a3b84db
commit 6639ab339a
6 changed files with 153 additions and 3 deletions
+2
View File
@@ -441,6 +441,8 @@ where
config.roles = role;
config.disable_grandpa = cli.no_grandpa;
config.grandpa_voter = cli.grandpa_voter;
let is_dev = cli.shared_params.dev;
+5
View File
@@ -305,6 +305,11 @@ pub struct RunCmd {
#[structopt(long = "no-grandpa")]
pub no_grandpa: bool,
/// Run GRANDPA voter even when no additional key seed via `--key` is specified. This can for example be of interest
/// when running a sentry node in front of a validator, thus needing to forward GRANDPA gossip messages.
#[structopt(long = "grandpa-voter")]
pub grandpa_voter: bool,
/// Experimental: Run in light client mode
#[structopt(long = "light")]
pub light: bool,
+4 -1
View File
@@ -87,6 +87,9 @@ pub struct Configuration<C, G: Serialize + DeserializeOwned + BuildStorage> {
pub force_authoring: bool,
/// Disable GRANDPA when running in validator mode
pub disable_grandpa: bool,
/// Run GRANDPA voter even when no additional key seed is specified. This can for example be of interest when
/// running a sentry node in front of a validator, thus needing to forward GRANDPA gossip messages.
pub grandpa_voter: bool,
/// Node keystore's password
pub password: Protected<String>,
}
@@ -122,6 +125,7 @@ impl<C: Default, G: Serialize + DeserializeOwned + BuildStorage> Configuration<C
offchain_worker: Default::default(),
force_authoring: false,
disable_grandpa: false,
grandpa_voter: false,
password: "".to_string().into(),
};
configuration.network.boot_nodes = configuration.chain_spec.boot_nodes().to_vec();
@@ -154,4 +158,3 @@ pub fn full_version_from_strs(impl_version: &str, impl_commit: &str) -> String {
let commit_dash = if impl_commit.is_empty() { "" } else { "-" };
format!("{}{}{}-{}", impl_version, commit_dash, impl_commit, platform())
}
+1
View File
@@ -194,6 +194,7 @@ fn node_config<F: ServiceFactory> (
offchain_worker: false,
force_authoring: false,
disable_grandpa: false,
grandpa_voter: false,
password: "".to_string().into(),
}
}
+3 -2
View File
@@ -125,7 +125,7 @@ construct_service_factory! {
};
match config.local_key {
None => {
None if !service.config.grandpa_voter => {
service.spawn_task(Box::new(grandpa::run_grandpa_observer(
config,
link_half,
@@ -133,7 +133,8 @@ construct_service_factory! {
service.on_exit(),
)?));
},
Some(_) => {
// Either config.local_key is set, or user forced voter service via `--grandpa-voter` flag.
_ => {
let telemetry_on_connect = TelemetryOnConnect {
telemetry_connection_sinks: service.telemetry_on_connect_stream(),
};
@@ -0,0 +1,138 @@
# Docker compose file to simulate a sentry node setup.
#
#
# Setup:
#
# Validator A is not supposed to be connected to the public internet. Instead it
# connects to a sentry node (sentry-a) which connects to the public internet.
# Validator B can reach validator A via sentry node A and vice versa.
#
#
# Usage:
#
# 1. Build `target/debug/substrate` binary: `cargo build`
#
# 2. Start networks and containers: `sudo docker-compose -f scripts/sentry-node/docker-compose.yml up`
#
# 3. Reach:
# - polkadot/apps on localhost:3000
# - validator-a: localhost:9944
# - validator-b: localhost:9945
# - sentry-a: localhost:9946
version: "3.7"
services:
validator-a:
ports:
- "9944:9944"
volumes:
- ../../target/debug/substrate:/usr/local/bin/substrate
image: parity/substrate
networks:
- network-a
command:
# Local node id: QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR
- "--node-key"
- "0000000000000000000000000000000000000000000000000000000000000001"
- "--base-path"
- "/tmp/alice"
- "--chain=local"
- "--key"
- "//Alice"
- "--port"
- "30333"
- "--validator"
- "--name"
- "AlicesNode"
- "--bootnodes"
- "/dns4/validator-b/tcp/30333/p2p/QmSVnNf9HwVMT1Y4cK1P6aoJcEZjmoTXpjKBmAABLMnZEk"
# Not only bind to localhost.
- "--ws-external"
- "--rpc-external"
# - "--log"
# - "sub-libp2p=trace"
# - "--log"
# - "afg=trace"
- "--no-telemetry"
- "--rpc-cors"
- "all"
sentry-a:
image: parity/substrate
ports:
- "9946:9944"
volumes:
- ../../target/debug/substrate:/usr/local/bin/substrate
networks:
- network-a
- internet
command:
# Local node id: QmV7EhW6J6KgmNdr558RH1mPx2xGGznW7At4BhXzntRFsi
- "--node-key"
- "0000000000000000000000000000000000000000000000000000000000000003"
- "--base-path"
- "/tmp/sentry"
- "--chain=local"
# Don't configure a key, as sentry-a is not a validator.
# - "--key"
# - "//Charlie"
- "--port"
- "30333"
# sentry-a is not a validator.
# - "--validator"
- "--name"
- "CharliesNode"
- "--bootnodes"
- "/dns4/validator-a/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR"
- "--bootnodes"
- "/dns4/validator-b/tcp/30333/p2p/QmSVnNf9HwVMT1Y4cK1P6aoJcEZjmoTXpjKBmAABLMnZEk"
- "--no-telemetry"
- "--rpc-cors"
- "all"
# Not only bind to localhost.
- "--ws-external"
- "--rpc-external"
# Make sure sentry-a still participates as a grandpa voter to forward
# grandpa finality gossip messages.
- "--grandpa-voter"
validator-b:
image: parity/substrate
ports:
- "9945:9944"
volumes:
- ../../target/debug/substrate:/usr/local/bin/substrate
networks:
- internet
command:
# Local node id: QmSVnNf9HwVMT1Y4cK1P6aoJcEZjmoTXpjKBmAABLMnZEk
- "--node-key"
- "0000000000000000000000000000000000000000000000000000000000000002"
- "--base-path"
- "/tmp/bob"
- "--chain=local"
- "--key"
- "//Bob"
- "--port"
- "30333"
- "--validator"
- "--name"
- "BobsNode"
- "--bootnodes"
- "/dns4/validator-a/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR"
- "--no-telemetry"
- "--rpc-cors"
- "all"
# Not only bind to localhost.
- "--ws-external"
- "--rpc-external"
ui:
image: polkadot-js/apps
ports:
- "3000:80"
networks:
network-a:
internet: