diff --git a/substrate/core/cli/src/lib.rs b/substrate/core/cli/src/lib.rs index 1868d79d746b32a51bb3840666d19a5b190379c5..dd47fb73bda364a34b0bd57dd5a5c84a97b5f75d 100644 --- a/substrate/core/cli/src/lib.rs +++ b/substrate/core/cli/src/lib.rs @@ -470,6 +470,8 @@ where config.telemetry_endpoints = Some(TelemetryEndpoints::new(cli.telemetry_endpoints)); } + config.force_authoring = cli.force_authoring; + Ok(config) } diff --git a/substrate/core/cli/src/params.rs b/substrate/core/cli/src/params.rs index d84f202501cd7c3458d6957e4680138e188c38a7..21ceafa20f674700366966a628e51a120e35e9f6 100644 --- a/substrate/core/cli/src/params.rs +++ b/substrate/core/cli/src/params.rs @@ -325,6 +325,10 @@ pub struct RunCmd { #[allow(missing_docs)] #[structopt(flatten)] pub keyring: Keyring, + + /// Enable authoring even when offline. + #[structopt(long = "force-authoring")] + pub force_authoring: bool, } /// Stores all required Cli values for a keyring test account. diff --git a/substrate/core/consensus/aura/src/lib.rs b/substrate/core/consensus/aura/src/lib.rs index e2c1091f14ad303be12438b0643c54691a5ef772..3a9bfd971abde77642f20049633971e3faa91fa2 100644 --- a/substrate/core/consensus/aura/src/lib.rs +++ b/substrate/core/consensus/aura/src/lib.rs @@ -160,6 +160,7 @@ pub fn start_aura_thread<B, C, E, I, P, SO, Error, OnExit>( sync_oracle: SO, on_exit: OnExit, inherent_data_providers: InherentDataProviders, + force_authoring: bool, ) -> Result<(), consensus_common::Error> where B: Block + 'static, C: Authorities<B> + ChainHead<B> + Send + Sync + 'static, @@ -176,7 +177,13 @@ pub fn start_aura_thread<B, C, E, I, P, SO, Error, OnExit>( Error: ::std::error::Error + Send + From<::consensus_common::Error> + 'static, { let worker = AuraWorker { - client: client.clone(), block_import, env, local_key, inherent_data_providers: inherent_data_providers.clone(), sync_oracle: sync_oracle.clone(), + client: client.clone(), + block_import, + env, + local_key, + inherent_data_providers: inherent_data_providers.clone(), + sync_oracle: sync_oracle.clone(), + force_authoring, }; aura_slots::start_slot_worker_thread::<_, _, _, _, AuraSlotCompatible, _>( @@ -199,6 +206,7 @@ pub fn start_aura<B, C, E, I, P, SO, Error, OnExit>( sync_oracle: SO, on_exit: OnExit, inherent_data_providers: InherentDataProviders, + force_authoring: bool, ) -> Result<impl Future<Item=(), Error=()>, consensus_common::Error> where B: Block, C: Authorities<B> + ChainHead<B>, @@ -215,7 +223,13 @@ pub fn start_aura<B, C, E, I, P, SO, Error, OnExit>( OnExit: Future<Item=(), Error=()>, { let worker = AuraWorker { - client: client.clone(), block_import, env, local_key, inherent_data_providers: inherent_data_providers.clone(), sync_oracle: sync_oracle.clone(), + client: client.clone(), + block_import, + env, + local_key, + inherent_data_providers: inherent_data_providers.clone(), + sync_oracle: sync_oracle.clone(), + force_authoring, }; aura_slots::start_slot_worker::<_, _, _, _, AuraSlotCompatible, _>( slot_duration, @@ -234,6 +248,7 @@ struct AuraWorker<C, E, I, P, SO> { local_key: Arc<P>, sync_oracle: SO, inherent_data_providers: InherentDataProviders, + force_authoring: bool, } impl<B: Block, C, E, I, P, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, P, SO> where @@ -287,7 +302,7 @@ impl<B: Block, C, E, I, P, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, P, S } }; - if self.sync_oracle.is_offline() && authorities.len() > 1 { + if !self.force_authoring && self.sync_oracle.is_offline() && authorities.len() > 1 { debug!(target: "aura", "Skipping proposal slot. Waiting for the network."); telemetry!(CONSENSUS_DEBUG; "aura.skipping_proposal_slot"; "authorities_len" => authorities.len() @@ -808,6 +823,7 @@ mod tests { DummyOracle, futures::empty(), inherent_data_providers, + false, ).expect("Starts aura"); runtime.spawn(aura); diff --git a/substrate/core/service/src/config.rs b/substrate/core/service/src/config.rs index d61f5a23845f92b8f87a3ce8c6a0a44553da4531..e7503d0ad2c69e7d02fa5068459f0405c09118ec 100644 --- a/substrate/core/service/src/config.rs +++ b/substrate/core/service/src/config.rs @@ -68,6 +68,8 @@ pub struct Configuration<C, G: Serialize + DeserializeOwned + BuildStorage> { pub telemetry_endpoints: Option<TelemetryEndpoints>, /// The default number of 64KB pages to allocate for Wasm execution pub default_heap_pages: Option<u64>, + /// Enable authoring even when offline. + pub force_authoring: bool, } impl<C: Default, G: Serialize + DeserializeOwned + BuildStorage> Configuration<C, G> { @@ -93,6 +95,7 @@ impl<C: Default, G: Serialize + DeserializeOwned + BuildStorage> Configuration<C rpc_ws: None, telemetry_endpoints: None, default_heap_pages: None, + force_authoring: false, }; configuration.network.boot_nodes = configuration.chain_spec.boot_nodes().to_vec(); diff --git a/substrate/core/service/test/src/lib.rs b/substrate/core/service/test/src/lib.rs index 72372f9292a33751cd8595503c9999134a8c4073..c6e13616720b4ef275df3c87987cb3f8ea61f236 100644 --- a/substrate/core/service/test/src/lib.rs +++ b/substrate/core/service/test/src/lib.rs @@ -120,6 +120,7 @@ fn node_config<F: ServiceFactory> ( rpc_ws: None, telemetry_endpoints: None, default_heap_pages: None, + force_authoring: false, } } diff --git a/substrate/node-template/src/service.rs b/substrate/node-template/src/service.rs index ae98d01de41e4e7394f94093e621a525b64279d2..5f1a375181675cdf9e8929050a05c716eb47ce51 100644 --- a/substrate/node-template/src/service.rs +++ b/substrate/node-template/src/service.rs @@ -73,6 +73,7 @@ construct_service_factory! { service.network(), service.on_exit(), service.config.custom.inherent_data_providers.clone(), + service.config.force_authoring, )?); } diff --git a/substrate/node/cli/src/service.rs b/substrate/node/cli/src/service.rs index bd1b89f0e60cd493b88e47bc5ea9f9bc18ab005f..b65dbc7444209595a900316302ee64359b607130 100644 --- a/substrate/node/cli/src/service.rs +++ b/substrate/node/cli/src/service.rs @@ -97,6 +97,7 @@ construct_service_factory! { service.network(), service.on_exit(), service.config.custom.inherent_data_providers.clone(), + service.config.force_authoring, )?); info!("Running Grandpa session as Authority {}", key.public());