node: add sentry mode flag (#3959)

* node: add sentry mode flag

* cli: extend docs on validator and sentry modes

* service: add missing field in test Configuration

* node: Display instead of Debug when printing node role
This commit is contained in:
André Silva
2019-10-29 18:58:34 +00:00
committed by Bastian Köcher
parent dc14809804
commit c92eda9809
8 changed files with 79 additions and 10 deletions
+16 -1
View File
@@ -236,6 +236,17 @@ where
}
}
/// Returns a string displaying the node role, special casing the sentry mode
/// (returning `SENTRY`), since the node technically has an `AUTHORITY` role but
/// doesn't participate.
pub fn display_role<A, B>(config: &Configuration<(), A, B>) -> String {
if config.sentry_mode {
"SENTRY".to_string()
} else {
format!("{:?}", config.roles)
}
}
/// Output of calling `parse_and_prepare`.
#[must_use]
pub enum ParseAndPrepare<'a, CC, RP> {
@@ -658,16 +669,20 @@ where
config.state_cache_size = cli.state_cache_size;
let is_dev = cli.shared_params.dev;
let is_authority = cli.validator || cli.sentry || is_dev || cli.keyring.account.is_some();
let role =
if cli.light {
service::Roles::LIGHT
} else if cli.validator || is_dev || cli.keyring.account.is_some() {
} else if is_authority {
service::Roles::AUTHORITY
} else {
service::Roles::FULL
};
// set sentry mode (i.e. act as an authority but **never** actively participate)
config.sentry_mode = cli.sentry;
// by default we disable pruning if the node is an authority (i.e.
// `ArchiveAll`), otherwise we keep state for the last 256 blocks. if the
// node is an authority and pruning is enabled explicitly, then we error
+23 -1
View File
@@ -301,9 +301,31 @@ pub struct ExecutionStrategies {
#[derive(Debug, StructOpt, Clone)]
pub struct RunCmd {
/// Enable validator mode.
#[structopt(long = "validator")]
///
/// The node will be started with the authority role and actively
/// participate in any consensus task that it can (e.g. depending on
/// availability of local keys).
#[structopt(
long = "validator",
conflicts_with_all = &[ "sentry" ]
)]
pub validator: bool,
/// Enable sentry mode.
///
/// The node will be started with the authority role and participate in
/// consensus tasks as an "observer", it will never actively participate
/// regardless of whether it could (e.g. keys are available locally). This
/// mode is useful as a secure proxy for validators (which would run
/// detached from the network), since we want this node to participate in
/// the full consensus protocols in order to have all needed consensus data
/// available to relay to private nodes.
#[structopt(
long = "sentry",
conflicts_with_all = &[ "validator" ]
)]
pub sentry: bool,
/// Disable GRANDPA voter when running in validator mode, otherwise disables the GRANDPA observer.
#[structopt(long = "no-grandpa")]
pub no_grandpa: bool,
+5
View File
@@ -82,6 +82,10 @@ pub struct Configuration<C, G, E = NoExtension> {
pub default_heap_pages: Option<u64>,
/// Should offchain workers be executed.
pub offchain_worker: bool,
/// Sentry mode is enabled, the node's role is AUTHORITY but it should not
/// actively participate in consensus (i.e. no keystores should be passed to
/// consensus modules).
pub sentry_mode: bool,
/// Enable authoring even when offline.
pub force_authoring: bool,
/// Disable GRANDPA when running in validator mode
@@ -129,6 +133,7 @@ impl<C, G, E> Configuration<C, G, E> where
telemetry_external_transport: None,
default_heap_pages: None,
offchain_worker: Default::default(),
sentry_mode: false,
force_authoring: false,
disable_grandpa: false,
keystore_password: None,
+1
View File
@@ -188,6 +188,7 @@ fn node_config<G, E: Clone> (
telemetry_external_transport: None,
default_heap_pages: None,
offchain_worker: false,
sentry_mode: false,
force_authoring: false,
disable_grandpa: false,
dev_key_seed: key_seed,
+2 -2
View File
@@ -3,7 +3,7 @@ use futures::{future, Future, sync::oneshot};
use std::cell::RefCell;
use tokio::runtime::Runtime;
pub use substrate_cli::{VersionInfo, IntoExit, error};
use substrate_cli::{informant, parse_and_prepare, ParseAndPrepare, NoCustom};
use substrate_cli::{display_role, informant, parse_and_prepare, ParseAndPrepare, NoCustom};
use substrate_service::{AbstractService, Roles as ServiceRoles, Configuration};
use aura_primitives::sr25519::{AuthorityPair as AuraPair};
use crate::chain_spec;
@@ -24,7 +24,7 @@ pub fn run<I, T, E>(args: I, exit: E, version: VersionInfo) -> error::Result<()>
info!(" by {}, 2017, 2018", version.author);
info!("Chain specification: {}", config.chain_spec.name());
info!("Node name: {}", config.name);
info!("Roles: {:?}", config.roles);
info!("Roles: {}", display_role(&config));
let runtime = Runtime::new().map_err(|e| format!("{:?}", e))?;
match config.roles {
ServiceRoles::LIGHT => run_until_exit(
+15 -2
View File
@@ -80,6 +80,11 @@ pub fn new_full<C: Send + Default + 'static>(config: Configuration<C, GenesisCon
let name = config.name.clone();
let disable_grandpa = config.disable_grandpa;
// sentry nodes announce themselves as authorities to the network
// and should run the same protocols authorities do, but it should
// never actively participate in any consensus process.
let participates_in_consensus = is_authority && !config.sentry_mode;
let (builder, mut import_setup, inherent_data_providers) = new_full_start!(config);
let (block_import, grandpa_link) =
@@ -92,7 +97,7 @@ pub fn new_full<C: Send + Default + 'static>(config: Configuration<C, GenesisCon
)?
.build()?;
if is_authority {
if participates_in_consensus {
let proposer = basic_authorship::ProposerFactory {
client: service.client(),
transaction_pool: service.transaction_pool(),
@@ -119,13 +124,21 @@ pub fn new_full<C: Send + Default + 'static>(config: Configuration<C, GenesisCon
service.spawn_essential_task(aura);
}
// if the node isn't actively participating in consensus then it doesn't
// need a keystore, regardless of which protocol we use below.
let keystore = if participates_in_consensus {
Some(service.keystore())
} else {
None
};
let grandpa_config = grandpa::Config {
// FIXME #1578 make this available through chainspec
gossip_duration: Duration::from_millis(333),
justification_period: 512,
name: Some(name),
keystore: Some(service.keystore()),
observer_enabled: true,
keystore,
is_authority,
};
+2 -2
View File
@@ -31,7 +31,7 @@ pub use cli::{VersionInfo, IntoExit, NoCustom, SharedParams, ExecutionStrategyPa
use substrate_service::{AbstractService, Roles as ServiceRoles, Configuration};
use log::info;
use structopt::{StructOpt, clap::App};
use cli::{AugmentClap, GetLogFilter, parse_and_prepare, ParseAndPrepare};
use cli::{display_role, parse_and_prepare, AugmentClap, GetLogFilter, ParseAndPrepare};
use crate::factory_impl::FactoryState;
use transaction_factory::RuntimeAdapter;
use client::ExecutionStrategies;
@@ -166,7 +166,7 @@ pub fn run<I, T, E>(args: I, exit: E, version: cli::VersionInfo) -> error::Resul
info!(" by Parity Technologies, 2017-2019");
info!("Chain specification: {}", config.chain_spec.name());
info!("Node name: {}", config.name);
info!("Roles: {:?}", config.roles);
info!("Roles: {}", display_role(&config));
let runtime = RuntimeBuilder::new().name_prefix("main-tokio-").build()
.map_err(|e| format!("{:?}", e))?;
match config.roles {
+15 -2
View File
@@ -124,6 +124,11 @@ macro_rules! new_full {
$config.disable_grandpa
);
// sentry nodes announce themselves as authorities to the network
// and should run the same protocols authorities do, but it should
// never actively participate in any consensus process.
let participates_in_consensus = is_authority && !$config.sentry_mode;
let (builder, mut import_setup, inherent_data_providers) = new_full_start!($config);
// Dht event channel from the network to the authority discovery module. Use bounded channel to ensure
@@ -145,7 +150,7 @@ macro_rules! new_full {
($with_startup_data)(&block_import, &babe_link);
if is_authority {
if participates_in_consensus {
let proposer = substrate_basic_authorship::ProposerFactory {
client: service.client(),
transaction_pool: service.transaction_pool(),
@@ -171,13 +176,21 @@ macro_rules! new_full {
service.spawn_essential_task(babe);
}
// if the node isn't actively participating in consensus then it doesn't
// need a keystore, regardless of which protocol we use below.
let keystore = if participates_in_consensus {
Some(service.keystore())
} else {
None
};
let config = grandpa::Config {
// FIXME #1578 make this available through chainspec
gossip_duration: std::time::Duration::from_millis(333),
justification_period: 512,
name: Some(name),
keystore: Some(service.keystore()),
observer_enabled: true,
keystore,
is_authority,
};