diff --git a/substrate/core/cli/src/lib.rs b/substrate/core/cli/src/lib.rs index a22278b830..2baeb46bdc 100644 --- a/substrate/core/cli/src/lib.rs +++ b/substrate/core/cli/src/lib.rs @@ -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; diff --git a/substrate/core/cli/src/params.rs b/substrate/core/cli/src/params.rs index 0cdc633188..77e42fa192 100644 --- a/substrate/core/cli/src/params.rs +++ b/substrate/core/cli/src/params.rs @@ -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, diff --git a/substrate/core/service/src/config.rs b/substrate/core/service/src/config.rs index 5db9b756a1..6f2f51ebfb 100644 --- a/substrate/core/service/src/config.rs +++ b/substrate/core/service/src/config.rs @@ -87,6 +87,9 @@ pub struct Configuration { 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, } @@ -122,6 +125,7 @@ impl Configuration String { let commit_dash = if impl_commit.is_empty() { "" } else { "-" }; format!("{}{}{}-{}", impl_version, commit_dash, impl_commit, platform()) } - diff --git a/substrate/core/service/test/src/lib.rs b/substrate/core/service/test/src/lib.rs index 4dbdd22753..adfee10029 100644 --- a/substrate/core/service/test/src/lib.rs +++ b/substrate/core/service/test/src/lib.rs @@ -194,6 +194,7 @@ fn node_config ( offchain_worker: false, force_authoring: false, disable_grandpa: false, + grandpa_voter: false, password: "".to_string().into(), } } diff --git a/substrate/node/cli/src/service.rs b/substrate/node/cli/src/service.rs index 25382d148e..3dcaf85d6a 100644 --- a/substrate/node/cli/src/service.rs +++ b/substrate/node/cli/src/service.rs @@ -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(), }; diff --git a/substrate/scripts/sentry-node/docker-compose.yml b/substrate/scripts/sentry-node/docker-compose.yml new file mode 100644 index 0000000000..e784b29f9f --- /dev/null +++ b/substrate/scripts/sentry-node/docker-compose.yml @@ -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: