Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

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

Merged
merged 2 commits into from
Jul 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions core/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
5 changes: 5 additions & 0 deletions core/cli/src/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
5 changes: 4 additions & 1 deletion core/service/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
}
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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 change: 1 addition & 0 deletions core/service/test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
}
}
Expand Down
5 changes: 3 additions & 2 deletions node/cli/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,16 @@ 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,
service.network(),
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(),
};
Expand Down
138 changes: 138 additions & 0 deletions scripts/sentry-node/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -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"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use --reserved-nodes here instead? Same for the other nodes configs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind adding some more details @andresilva?

If I understand correctly, validator addresses can change at runtime. Thus if the address of validator-b changes, sentry-a would need to be restarted. I would suggest only interconnecting validator-a and sentry-a as reserved nodes and sentry-a and validator-b as bootstrap nodes, given that a and b are controlled by different entities.

What do you think?

On a side note, I am currently looking into how a user can tell a validator node to keep x amount of connections open to other validator nodes. As the validator address set can change at runtime, these long-lived connections would also be adjusted along the way.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this config A connects to B (through bootnodes). The sentry connects to A and B, and B also tries to connect with A.

My understanding is that in a real scenario the validator nodes that are using a sentry will only be connected to the sentry (or multiple sentries). So I think in this config Validator-A should set Sentry-A as a reserved node (so that it only connects to this node), and the rest of the nodes (Sentry-A and Validator-B) can add everyone as bootnode (even though Validator-B won't be able to connect to Validator-A).

- "/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: