Dual execution (#311)

* Initial logic

* Remove accidental file

* Config

* Remove accidental

* Apply CLI config

* Additional work. Sadly pointless.

* Rearrange everything

* Loop into CLI param

* Implement dual execution

* typo

* fix tests.

* Better docs

* Fix bug

* Add some tests

* Report block information on consensus failure, tests

* Fix test
This commit is contained in:
Gav Wood
2018-07-14 16:10:20 +02:00
committed by GitHub
parent b1327624cd
commit c2f78371f1
5 changed files with 33 additions and 11 deletions
+5 -1
View File
@@ -74,7 +74,7 @@ args:
- pruning: - pruning:
long: pruning long: pruning
value_name: PRUNING_MODE value_name: PRUNING_MODE
help: Specify the pruning mode. (a number of blocks to keep or "archive"). Default is 256. help: Specify the pruning mode, a number of blocks to keep or "archive". Default is 256.
takes_value: true takes_value: true
- name: - name:
long: name long: name
@@ -95,6 +95,10 @@ args:
value_name: TELEMETRY_URL value_name: TELEMETRY_URL
help: The URL of the telemetry server. Implies --telemetry help: The URL of the telemetry server. Implies --telemetry
takes_value: true takes_value: true
- execution:
long: execution
value_name: STRATEGY
help: The means of execution used when calling into the runtime. Can be either wasm, native or both.
subcommands: subcommands:
- build-spec: - build-spec:
about: Build a spec.json file, outputing to stdout about: Build a spec.json file, outputing to stdout
+15 -1
View File
@@ -218,18 +218,32 @@ pub fn run<I, T, W>(args: I, worker: W) -> error::Result<()> where
if matches.is_present("collator") { if matches.is_present("collator") {
info!("Starting collator"); info!("Starting collator");
// TODO [rob]: collation node implementation // TODO [rob]: collation node implementation
service::Role::FULL // This isn't a thing. Different parachains will have their own collator executables and
// maybe link to libpolkadot to get a light-client.
service::Role::LIGHT
} else if matches.is_present("light") { } else if matches.is_present("light") {
info!("Starting (light)"); info!("Starting (light)");
config.execution_strategy = service::ExecutionStrategy::NativeWhenPossible;
service::Role::LIGHT service::Role::LIGHT
} else if matches.is_present("validator") || matches.is_present("dev") { } else if matches.is_present("validator") || matches.is_present("dev") {
info!("Starting validator"); info!("Starting validator");
config.execution_strategy = service::ExecutionStrategy::Both;
service::Role::AUTHORITY service::Role::AUTHORITY
} else { } else {
info!("Starting (heavy)"); info!("Starting (heavy)");
config.execution_strategy = service::ExecutionStrategy::NativeWhenPossible;
service::Role::FULL service::Role::FULL
}; };
if let Some(s) = matches.value_of("execution") {
config.execution_strategy = match s {
"both" => service::ExecutionStrategy::Both,
"native" => service::ExecutionStrategy::NativeWhenPossible,
"wasm" => service::ExecutionStrategy::AlwaysWasm,
_ => return Err(error::ErrorKind::Input("Invalid execution mode specified".to_owned()).into()),
};
}
config.roles = role; config.roles = role;
{ {
config.network.boot_nodes.extend(matches config.network.boot_nodes.extend(matches
+5 -5
View File
@@ -30,7 +30,7 @@ use polkadot_api;
use polkadot_executor::Executor as LocalDispatch; use polkadot_executor::Executor as LocalDispatch;
use polkadot_network::NetworkService; use polkadot_network::NetworkService;
use polkadot_primitives::{Block, BlockId, Hash}; use polkadot_primitives::{Block, BlockId, Hash};
use state_machine; use state_machine::{self, ExecutionStrategy};
use substrate_executor::NativeExecutor; use substrate_executor::NativeExecutor;
use transaction_pool::{self, TransactionPool}; use transaction_pool::{self, TransactionPool};
use tokio::runtime::TaskExecutor; use tokio::runtime::TaskExecutor;
@@ -50,7 +50,7 @@ pub trait Components {
type Executor: 'static + client::CallExecutor<Block> + Send + Sync; type Executor: 'static + client::CallExecutor<Block> + Send + Sync;
/// Create client. /// Create client.
fn build_client(&self, settings: client_db::DatabaseSettings, executor: CodeExecutor, chain_spec: &ChainSpec) fn build_client(&self, settings: client_db::DatabaseSettings, executor: CodeExecutor, chain_spec: &ChainSpec, execution_strategy: ExecutionStrategy)
-> Result<(Arc<Client<Self::Backend, Self::Executor, Block>>, Option<Arc<OnDemand<Block, NetworkService>>>), error::Error>; -> Result<(Arc<Client<Self::Backend, Self::Executor, Block>>, Option<Arc<OnDemand<Block, NetworkService>>>), error::Error>;
/// Create api. /// Create api.
@@ -83,9 +83,9 @@ impl Components for FullComponents {
type Api = Client<Self::Backend, Self::Executor, Block>; type Api = Client<Self::Backend, Self::Executor, Block>;
type Executor = client::LocalCallExecutor<client_db::Backend<Block>, NativeExecutor<LocalDispatch>>; type Executor = client::LocalCallExecutor<client_db::Backend<Block>, NativeExecutor<LocalDispatch>>;
fn build_client(&self, db_settings: client_db::DatabaseSettings, executor: CodeExecutor, chain_spec: &ChainSpec) fn build_client(&self, db_settings: client_db::DatabaseSettings, executor: CodeExecutor, chain_spec: &ChainSpec, execution_strategy: ExecutionStrategy)
-> Result<(Arc<client::Client<Self::Backend, Self::Executor, Block>>, Option<Arc<OnDemand<Block, NetworkService>>>), error::Error> { -> Result<(Arc<client::Client<Self::Backend, Self::Executor, Block>>, Option<Arc<OnDemand<Block, NetworkService>>>), error::Error> {
Ok((Arc::new(client_db::new_client(db_settings, executor, chain_spec)?), None)) Ok((Arc::new(client_db::new_client(db_settings, executor, chain_spec, execution_strategy)?), None))
} }
fn build_api(&self, client: Arc<client::Client<Self::Backend, Self::Executor, Block>>) -> Arc<Self::Api> { fn build_api(&self, client: Arc<client::Client<Self::Backend, Self::Executor, Block>>) -> Arc<Self::Api> {
@@ -142,7 +142,7 @@ impl Components for LightComponents {
client::light::blockchain::Blockchain<client_db::light::LightStorage<Block>, network::OnDemand<Block, NetworkService>>, client::light::blockchain::Blockchain<client_db::light::LightStorage<Block>, network::OnDemand<Block, NetworkService>>,
network::OnDemand<Block, NetworkService>>; network::OnDemand<Block, NetworkService>>;
fn build_client(&self, db_settings: client_db::DatabaseSettings, executor: CodeExecutor, spec: &ChainSpec) fn build_client(&self, db_settings: client_db::DatabaseSettings, executor: CodeExecutor, spec: &ChainSpec, _execution_strategy: ExecutionStrategy)
-> Result<(Arc<client::Client<Self::Backend, Self::Executor, Block>>, Option<Arc<OnDemand<Block, NetworkService>>>), error::Error> { -> Result<(Arc<client::Client<Self::Backend, Self::Executor, Block>>, Option<Arc<OnDemand<Block, NetworkService>>>), error::Error> {
let db_storage = client_db::light::LightStorage::new(db_settings)?; let db_storage = client_db::light::LightStorage::new(db_settings)?;
let light_blockchain = client::light::new_light_blockchain(db_storage); let light_blockchain = client::light::new_light_blockchain(db_storage);
+4
View File
@@ -18,6 +18,7 @@
use transaction_pool; use transaction_pool;
use chain_spec::ChainSpec; use chain_spec::ChainSpec;
pub use state_machine::ExecutionStrategy;
pub use network::Role; pub use network::Role;
pub use network::NetworkConfiguration; pub use network::NetworkConfiguration;
pub use client_db::PruningMode; pub use client_db::PruningMode;
@@ -44,6 +45,8 @@ pub struct Configuration {
pub telemetry: Option<String>, pub telemetry: Option<String>,
/// Node name. /// Node name.
pub name: String, pub name: String,
/// Execution strategy.
pub execution_strategy: ExecutionStrategy,
} }
impl Configuration { impl Configuration {
@@ -60,6 +63,7 @@ impl Configuration {
keys: Default::default(), keys: Default::default(),
telemetry: Default::default(), telemetry: Default::default(),
pruning: PruningMode::ArchiveAll, pruning: PruningMode::ArchiveAll,
execution_strategy: ExecutionStrategy::Both,
}; };
configuration.network.boot_nodes = configuration.chain_spec.boot_nodes().to_vec(); configuration.network.boot_nodes = configuration.chain_spec.boot_nodes().to_vec();
configuration configuration
+4 -4
View File
@@ -73,7 +73,7 @@ use tokio::runtime::TaskExecutor;
pub use self::error::{ErrorKind, Error}; pub use self::error::{ErrorKind, Error};
pub use self::components::{Components, FullComponents, LightComponents}; pub use self::components::{Components, FullComponents, LightComponents};
pub use config::{Configuration, Role, PruningMode}; pub use config::{Configuration, Role, PruningMode, ExecutionStrategy};
pub use chain_spec::ChainSpec; pub use chain_spec::ChainSpec;
/// Polkadot service. /// Polkadot service.
@@ -112,7 +112,7 @@ pub fn new_client(config: Configuration) -> Result<Arc<Client<
let executor = polkadot_executor::Executor::new(); let executor = polkadot_executor::Executor::new();
let is_validator = (config.roles & Role::AUTHORITY) == Role::AUTHORITY; let is_validator = (config.roles & Role::AUTHORITY) == Role::AUTHORITY;
let components = components::FullComponents { is_validator }; let components = components::FullComponents { is_validator };
let (client, _) = components.build_client(db_settings, executor, &config.chain_spec)?; let (client, _) = components.build_client(db_settings, executor, &config.chain_spec, config.execution_strategy)?;
Ok(client) Ok(client)
} }
@@ -126,7 +126,7 @@ impl<Components> Service<Components>
let (signal, exit) = ::exit_future::signal(); let (signal, exit) = ::exit_future::signal();
// Create client // Create client
let executor = polkadot_executor::Executor::new(); let executor = polkadot_executor::Executor::with_heap_pages(128);
let mut keystore = Keystore::open(config.keystore_path.into())?; let mut keystore = Keystore::open(config.keystore_path.into())?;
for seed in &config.keys { for seed in &config.keys {
@@ -144,7 +144,7 @@ impl<Components> Service<Components>
pruning: config.pruning, pruning: config.pruning,
}; };
let (client, on_demand) = components.build_client(db_settings, executor, &config.chain_spec)?; let (client, on_demand) = components.build_client(db_settings, executor, &config.chain_spec, config.execution_strategy)?;
let api = components.build_api(client.clone()); let api = components.build_api(client.clone());
let best_header = client.best_block_header()?; let best_header = client.best_block_header()?;