diff --git a/client/cli/src/arg_enums.rs b/client/cli/src/arg_enums.rs index 4dfd384d9513c..db13fff76148e 100644 --- a/client/cli/src/arg_enums.rs +++ b/client/cli/src/arg_enums.rs @@ -178,6 +178,8 @@ arg_enum! { pub const DEFAULT_EXECUTION_SYNCING: ExecutionStrategy = ExecutionStrategy::NativeElseWasm; /// Default value for the `--execution-import-block` parameter. pub const DEFAULT_EXECUTION_IMPORT_BLOCK: ExecutionStrategy = ExecutionStrategy::NativeElseWasm; +/// Default value for the `--execution-import-block` parameter when the node is a validator. +pub const DEFAULT_EXECUTION_IMPORT_BLOCK_VALIDATOR: ExecutionStrategy = ExecutionStrategy::Wasm; /// Default value for the `--execution-block-construction` parameter. pub const DEFAULT_EXECUTION_BLOCK_CONSTRUCTION: ExecutionStrategy = ExecutionStrategy::Wasm; /// Default value for the `--execution-offchain-worker` parameter. diff --git a/client/cli/src/commands/mod.rs b/client/cli/src/commands/mod.rs index 62757890ef01d..dececb2a90245 100644 --- a/client/cli/src/commands/mod.rs +++ b/client/cli/src/commands/mod.rs @@ -278,10 +278,10 @@ macro_rules! substrate_cli_subcommands { } } - fn execution_strategies(&self, is_dev: bool) + fn execution_strategies(&self, is_dev: bool, is_validator: bool) -> $crate::Result<::sc_client_api::execution_extensions::ExecutionStrategies> { match self { - $($enum::$variant(cmd) => cmd.execution_strategies(is_dev)),* + $($enum::$variant(cmd) => cmd.execution_strategies(is_dev, is_validator)),* } } @@ -409,4 +409,3 @@ macro_rules! substrate_cli_subcommands { substrate_cli_subcommands!( Subcommand => BuildSpec, ExportBlocks, ImportBlocks, CheckBlock, Revert, PurgeChain, ExportState ); - diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index a1ee1b0cc1da9..90e5f98e3d871 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -246,9 +246,14 @@ pub trait CliConfiguration: Sized { /// /// By default this is retrieved from `ImportParams` if it is available. Otherwise its /// `ExecutionStrategies::default()`. - fn execution_strategies(&self, is_dev: bool) -> Result { - Ok(self.import_params() - .map(|x| x.execution_strategies(is_dev)) + fn execution_strategies( + &self, + is_dev: bool, + is_validator: bool, + ) -> Result { + Ok(self + .import_params() + .map(|x| x.execution_strategies(is_dev, is_validator)) .unwrap_or(Default::default())) } @@ -419,6 +424,7 @@ pub trait CliConfiguration: Sized { let node_key = self.node_key(&net_config_dir)?; let role = self.role(is_dev)?; let max_runtime_instances = self.max_runtime_instances()?.unwrap_or(8); + let is_validator = role.is_network_authority(); let unsafe_pruning = self .import_params() @@ -444,7 +450,7 @@ pub trait CliConfiguration: Sized { state_cache_child_ratio: self.state_cache_child_ratio()?, pruning: self.pruning(unsafe_pruning, &role)?, wasm_method: self.wasm_method()?, - execution_strategies: self.execution_strategies(is_dev)?, + execution_strategies: self.execution_strategies(is_dev, is_validator)?, rpc_http: self.rpc_http()?, rpc_ws: self.rpc_ws()?, rpc_methods: self.rpc_methods()?, diff --git a/client/cli/src/params/import_params.rs b/client/cli/src/params/import_params.rs index fb683df6d3be9..60bd6e6643443 100644 --- a/client/cli/src/params/import_params.rs +++ b/client/cli/src/params/import_params.rs @@ -17,8 +17,8 @@ // along with this program. If not, see . use crate::arg_enums::{ - ExecutionStrategy, TracingReceiver, WasmExecutionMethod, - DEFAULT_EXECUTION_BLOCK_CONSTRUCTION, DEFAULT_EXECUTION_IMPORT_BLOCK, + ExecutionStrategy, TracingReceiver, WasmExecutionMethod, DEFAULT_EXECUTION_BLOCK_CONSTRUCTION, + DEFAULT_EXECUTION_IMPORT_BLOCK, DEFAULT_EXECUTION_IMPORT_BLOCK_VALIDATOR, DEFAULT_EXECUTION_OFFCHAIN_WORKER, DEFAULT_EXECUTION_OTHER, DEFAULT_EXECUTION_SYNCING, }; use crate::params::DatabaseParams; @@ -104,22 +104,27 @@ impl ImportParams { } /// Get execution strategies for the parameters - pub fn execution_strategies( - &self, - is_dev: bool, - ) -> ExecutionStrategies { + pub fn execution_strategies(&self, is_dev: bool, is_validator: bool) -> ExecutionStrategies { let exec = &self.execution_strategies; - let exec_all_or = |strat: ExecutionStrategy, default: ExecutionStrategy| { - exec.execution.unwrap_or(if strat == default && is_dev { + let exec_all_or = |strat: Option, default: ExecutionStrategy| { + let default = if is_dev { ExecutionStrategy::Native } else { - strat - }).into() + default + }; + + exec.execution.unwrap_or(strat.unwrap_or(default)).into() + }; + + let default_execution_import_block = if is_validator { + DEFAULT_EXECUTION_IMPORT_BLOCK_VALIDATOR + } else { + DEFAULT_EXECUTION_IMPORT_BLOCK }; ExecutionStrategies { syncing: exec_all_or(exec.execution_syncing, DEFAULT_EXECUTION_SYNCING), - importing: exec_all_or(exec.execution_import_block, DEFAULT_EXECUTION_IMPORT_BLOCK), + importing: exec_all_or(exec.execution_import_block, default_execution_import_block), block_construction: exec_all_or(exec.execution_block_construction, DEFAULT_EXECUTION_BLOCK_CONSTRUCTION), offchain_worker: @@ -132,25 +137,25 @@ impl ImportParams { /// Execution strategies parameters. #[derive(Debug, StructOpt, Clone)] pub struct ExecutionStrategiesParams { - /// The means of execution used when calling into the runtime while syncing blocks. + /// The means of execution used when calling into the runtime for importing blocks as + /// part of an initial sync. #[structopt( long = "execution-syncing", value_name = "STRATEGY", possible_values = &ExecutionStrategy::variants(), case_insensitive = true, - default_value = DEFAULT_EXECUTION_SYNCING.as_str(), )] - pub execution_syncing: ExecutionStrategy, + pub execution_syncing: Option, - /// The means of execution used when calling into the runtime while importing blocks. + /// The means of execution used when calling into the runtime for general block import + /// (including locally authored blocks). #[structopt( long = "execution-import-block", value_name = "STRATEGY", possible_values = &ExecutionStrategy::variants(), case_insensitive = true, - default_value = DEFAULT_EXECUTION_IMPORT_BLOCK.as_str(), )] - pub execution_import_block: ExecutionStrategy, + pub execution_import_block: Option, /// The means of execution used when calling into the runtime while constructing blocks. #[structopt( @@ -158,9 +163,8 @@ pub struct ExecutionStrategiesParams { value_name = "STRATEGY", possible_values = &ExecutionStrategy::variants(), case_insensitive = true, - default_value = DEFAULT_EXECUTION_BLOCK_CONSTRUCTION.as_str(), )] - pub execution_block_construction: ExecutionStrategy, + pub execution_block_construction: Option, /// The means of execution used when calling into the runtime while using an off-chain worker. #[structopt( @@ -168,9 +172,8 @@ pub struct ExecutionStrategiesParams { value_name = "STRATEGY", possible_values = &ExecutionStrategy::variants(), case_insensitive = true, - default_value = DEFAULT_EXECUTION_OFFCHAIN_WORKER.as_str(), )] - pub execution_offchain_worker: ExecutionStrategy, + pub execution_offchain_worker: Option, /// The means of execution used when calling into the runtime while not syncing, importing or constructing blocks. #[structopt( @@ -178,9 +181,8 @@ pub struct ExecutionStrategiesParams { value_name = "STRATEGY", possible_values = &ExecutionStrategy::variants(), case_insensitive = true, - default_value = DEFAULT_EXECUTION_OTHER.as_str(), )] - pub execution_other: ExecutionStrategy, + pub execution_other: Option, /// The execution strategy that should be used by all execution contexts. #[structopt( diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 77b3f065f43dd..aaa09e66eb881 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -28,8 +28,9 @@ use parking_lot::{Mutex, RwLock}; use codec::{Encode, Decode}; use hash_db::Prefix; use sp_core::{ - ChangesTrieConfiguration, convert_hash, NativeOrEncoded, - storage::{StorageKey, PrefixedStorageKey, StorageData, well_known_keys, ChildInfo}, + convert_hash, + storage::{well_known_keys, ChildInfo, PrefixedStorageKey, StorageData, StorageKey}, + ChangesTrieConfiguration, ExecutionContext, NativeOrEncoded, }; use sc_telemetry::{telemetry, SUBSTRATE_INFO}; use sp_runtime::{ @@ -754,11 +755,6 @@ impl Client where ) = storage_changes.into_inner(); if self.config.offchain_indexing_api { - // if let Some(mut offchain_storage) = self.backend.offchain_storage() { - // offchain_sc.iter().for_each(|(k,v)| { - // offchain_storage.set(b"block-import-info", k,v) - // }); - // } operation.op.update_offchain_storage(offchain_sc)?; } @@ -865,9 +861,15 @@ impl Client where // block. (true, ref mut storage_changes @ None, Some(ref body)) => { let runtime_api = self.runtime_api(); + let execution_context = if import_block.origin == BlockOrigin::NetworkInitialSync { + ExecutionContext::Syncing + } else { + ExecutionContext::Importing + }; - runtime_api.execute_block( + runtime_api.execute_block_with_context( &at, + execution_context, Block::new(import_block.header.clone(), body.clone()), )?; diff --git a/primitives/core/src/lib.rs b/primitives/core/src/lib.rs index 56dbbc7b7898d..5fbbf3ca6d5ee 100644 --- a/primitives/core/src/lib.rs +++ b/primitives/core/src/lib.rs @@ -93,9 +93,16 @@ pub use sp_std; /// Context for executing a call into the runtime. pub enum ExecutionContext { - /// Context for general importing (including own blocks). + /// Context used for general block import (including locally authored blocks). Importing, - /// Context used when syncing the blockchain. + /// Context used for importing blocks as part of an initial sync of the blockchain. + /// + /// We distinguish between major sync and import so that validators who are running + /// their initial sync (or catching up after some time offline) can use the faster + /// native runtime (since we can reasonably assume the network as a whole has already + /// come to a broad conensus on the block and it probably hasn't been crafted + /// specifically to attack this node), but when importing blocks at the head of the + /// chain in normal operation they can use the safer Wasm version. Syncing, /// Context used for block construction. BlockConstruction,