Skip to content

Commit

Permalink
Support both polkadot and kusama runtimes (paritytech#704)
Browse files Browse the repository at this point in the history
* Allow both polkadot and kusama runtimes

* Allow both polkadot and kusama runtimes

* Make `collator` build

* Removed kusama runtime

* Introduced common runtime

* Updated for latest substrate

* Updated CI targets

* Updated CI version check

* Removed unused dependency

* Pulled latests substrate

* Pulled latest substrate

* Fixed version

* Apply suggestions from code review

Co-Authored-By: Bastian Köcher <[email protected]>

* NEW_HEADS_IDENTIFIER moved to primitives

* Updated CI check script

* Fixed script

* Set epoch duration for polkadot

* ci: check_runtime for both runtimes

Co-authored-by: Bastian Köcher <[email protected]>
Co-authored-by: gabriel klawitter <[email protected]>
  • Loading branch information
3 people authored and gavofyork committed Jan 3, 2020
1 parent dd113a7 commit 9ff8c3a
Show file tree
Hide file tree
Showing 42 changed files with 1,956 additions and 648 deletions.
4 changes: 2 additions & 2 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,12 @@ check-web-wasm: &test
script:
# WASM support is in progress. As more and more crates support WASM, we
# should add entries here. See https://github.com/paritytech/polkadot/issues/625
- time cargo build --locked --target=wasm32-unknown-unknown --manifest-path executor/Cargo.toml
- time cargo build --locked --target=wasm32-unknown-unknown --manifest-path runtime/polkadot/Cargo.toml
- time cargo build --locked --target=wasm32-unknown-unknown --manifest-path runtime/kusama/Cargo.toml
- time cargo build --locked --target=wasm32-unknown-unknown --manifest-path erasure-coding/Cargo.toml
- time cargo build --locked --target=wasm32-unknown-unknown --manifest-path parachain/Cargo.toml
- time cargo build --locked --target=wasm32-unknown-unknown --manifest-path primitives/Cargo.toml
- time cargo build --locked --target=wasm32-unknown-unknown --manifest-path rpc/Cargo.toml
- time cargo build --locked --target=wasm32-unknown-unknown --manifest-path runtime/Cargo.toml
- time cargo build --locked --target=wasm32-unknown-unknown --manifest-path statement-table/Cargo.toml
- sccache -s

Expand Down
135 changes: 118 additions & 17 deletions Cargo.lock

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ members = [
"cli",
"collator",
"erasure-coding",
"executor",
"network",
"primitives",
"runtime",
"runtime/common",
"runtime/polkadot",
"runtime/kusama",
"service",
"statement-table",
"service",
Expand All @@ -37,7 +38,8 @@ members = [
"test-parachains/adder/collator",
]
exclude = [
"runtime/wasm",
"runtime/polkadot/wasm",
"runtime/kusama/wasm",
"test-parachains/adder/wasm",
]

Expand Down
1 change: 0 additions & 1 deletion availability-store/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ edition = "2018"
[dependencies]
polkadot-primitives = { path = "../primitives" }
polkadot-erasure-coding = { path = "../erasure-coding" }
polkadot-runtime = { path = "../runtime" }
parking_lot = "0.9.0"
derive_more = "0.99"
log = "0.4.8"
Expand Down
19 changes: 13 additions & 6 deletions cli/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,19 @@ impl Default for ChainSpec {
/// Get a chain config from a spec setting.
impl ChainSpec {
pub(crate) fn load(self) -> Result<service::ChainSpec, String> {
Ok(match self {
ChainSpec::Kusama => service::chain_spec::kusama_config()?,
ChainSpec::Development => service::chain_spec::development_config(),
ChainSpec::LocalTestnet => service::chain_spec::local_testnet_config(),
ChainSpec::StagingTestnet => service::chain_spec::staging_testnet_config(),
})
match self {
ChainSpec::Development => Ok(service::chain_spec::development_config()),
ChainSpec::LocalTestnet => Ok(service::chain_spec::local_testnet_config()),
ChainSpec::StagingTestnet => Ok(service::chain_spec::staging_testnet_config()),
ChainSpec::Kusama => service::chain_spec::kusama_config(),
}
}

pub(crate) fn is_kusama(&self) -> bool {
match self {
ChainSpec::Development | ChainSpec::LocalTestnet | ChainSpec::StagingTestnet => false,
ChainSpec::Kusama => true,
}
}

pub(crate) fn from(s: &str) -> Option<Self> {
Expand Down
217 changes: 111 additions & 106 deletions cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,53 +26,27 @@ mod browser;
use chain_spec::ChainSpec;
use futures::{
Future, FutureExt, TryFutureExt, future::select, channel::oneshot, compat::Future01CompatExt,
task::Spawn
};
use tokio::runtime::Runtime;
use log::{info, error};
use log::info;
use structopt::StructOpt;

pub use service::{
AbstractService, CustomConfiguration,
ProvideRuntimeApi, CoreApi, ParachainHost,
AbstractService, CustomConfiguration, ProvideRuntimeApi, CoreApi, ParachainHost, IsKusama, self,
WrappedExecutor
};

pub use cli::{VersionInfo, IntoExit, NoCustom};
pub use cli::{VersionInfo, IntoExit, NoCustom, SharedParams};
pub use cli::{display_role, error};

fn load_spec(id: &str) -> Result<Option<service::ChainSpec>, String> {
/// Load the `ChainSpec` for the given `id`.
pub fn load_spec(id: &str) -> Result<Option<service::ChainSpec>, String> {
Ok(match ChainSpec::from(id) {
Some(spec) => Some(spec.load()?),
None => None,
})
}

/// Additional worker making use of the node, to run asynchronously before shutdown.
///
/// This will be invoked with the service and spawn a future that resolves
/// when complete.
pub trait Worker: IntoExit {
/// A future that resolves when the work is done or the node should exit.
/// This will be run on a tokio runtime.
type Work: Future<Output=()> + Unpin + Send + 'static;

/// Return configuration for the polkadot node.
// TODO: make this the full configuration, so embedded nodes don't need
// string CLI args (https://github.com/paritytech/polkadot/issues/111)
fn configuration(&self) -> service::CustomConfiguration { Default::default() }

/// Do work and schedule exit.
fn work<S, SC, B, CE, SP>(self, service: &S, spawner: SP) -> Self::Work
where S: AbstractService<Block = service::Block, RuntimeApi = service::RuntimeApi,
Backend = B, SelectChain = SC,
NetworkSpecialization = service::PolkadotProtocol, CallExecutor = CE>,
SC: service::SelectChain<service::Block> + 'static,
B: service::Backend<service::Block, service::Blake2Hasher> + 'static,
CE: service::CallExecutor<service::Block, service::Blake2Hasher> + Clone + Send + Sync + 'static,
SP: Spawn + Clone + Send + Sync + 'static;
}

#[derive(Debug, StructOpt, Clone)]
enum PolkadotSubCommands {
#[structopt(name = "validation-worker", setting = structopt::clap::AppSettings::Hidden)]
Expand All @@ -96,81 +70,111 @@ struct PolkadotSubParams {
}

/// Parses polkadot specific CLI arguments and run the service.
pub fn run<W>(worker: W, version: cli::VersionInfo) -> error::Result<()> where
W: Worker,
{
match cli::parse_and_prepare::<PolkadotSubCommands, PolkadotSubParams, _>(
pub fn run<E: IntoExit>(exit: E, version: cli::VersionInfo) -> error::Result<()> {
let cmd = cli::parse_and_prepare::<PolkadotSubCommands, PolkadotSubParams, _>(
&version,
"parity-polkadot",
std::env::args(),
) {
cli::ParseAndPrepare::Run(cmd) => cmd.run(load_spec, worker,
|worker, _cli_args, custom_args, mut config| {
info!("{}", version.name);
info!(" version {}", config.full_version());
info!(" by {}, 2017-2019", version.author);
info!("Chain specification: {}", config.chain_spec.name());
if config.chain_spec.name().starts_with("Kusama") {
info!("----------------------------");
info!("This chain is not in any way");
info!(" endorsed by the ");
info!(" KUSAMA FOUNDATION ");
info!("----------------------------");
}
info!("Node name: {}", config.name);
info!("Roles: {}", display_role(&config));
config.custom = worker.configuration();
config.custom.authority_discovery_enabled = custom_args.authority_discovery_enabled;
let runtime = Runtime::new().map_err(|e| format!("{:?}", e))?;
match config.roles {
service::Roles::LIGHT =>
run_until_exit(
runtime,
service::new_light(config).map_err(|e| format!("{:?}", e))?,
worker
),
_ => run_until_exit(
);
if cmd
.shared_params()
.and_then(|p| p.chain.as_ref())
.and_then(|c| ChainSpec::from(c))
.map_or(false, |c| c.is_kusama())
{
execute_cmd_with_runtime::<
service::kusama_runtime::RuntimeApi,
service::KusamaExecutor,
service::kusama_runtime::UncheckedExtrinsic,
_
>(exit, &version, cmd)
} else {
execute_cmd_with_runtime::<
service::polkadot_runtime::RuntimeApi,
service::PolkadotExecutor,
service::polkadot_runtime::UncheckedExtrinsic,
_
>(exit, &version, cmd)
}
}

/// Execute the given `cmd` with the given runtime.
fn execute_cmd_with_runtime<R, D, E, X>(
exit: X,
version: &cli::VersionInfo,
cmd: cli::ParseAndPrepare<PolkadotSubCommands, PolkadotSubParams>,
) -> error::Result<()>
where
R: service::ConstructRuntimeApi<service::Block, service::TFullClient<service::Block, R, D>>
+ service::ConstructRuntimeApi<service::Block, service::TLightClient<service::Block, R, D>>
+ Send + Sync + 'static,
<R as service::ConstructRuntimeApi<service::Block, service::TFullClient<service::Block, R, D>>>::RuntimeApi: service::RuntimeApiCollection<E>,
<R as service::ConstructRuntimeApi<service::Block, service::TLightClient<service::Block, R, D>>>::RuntimeApi: service::RuntimeApiCollection<E>,
E: service::Codec + Send + Sync + 'static,
D: service::NativeExecutionDispatch + 'static,
X: IntoExit,
{
match cmd {
cli::ParseAndPrepare::Run(cmd) => cmd.run(&load_spec, exit,
|exit, _cli_args, custom_args, mut config| {
info!("{}", version.name);
info!(" version {}", config.full_version());
info!(" by {}, 2017-2019", version.author);
info!("Chain specification: {}", config.chain_spec.name());
if config.is_kusama() {
info!("----------------------------");
info!("This chain is not in any way");
info!(" endorsed by the ");
info!(" KUSAMA FOUNDATION ");
info!("----------------------------");
}
info!("Node name: {}", config.name);
info!("Roles: {}", display_role(&config));
config.custom = service::CustomConfiguration::default();
config.custom.authority_discovery_enabled = custom_args.authority_discovery_enabled;
let runtime = Runtime::new().map_err(|e| format!("{:?}", e))?;
match config.roles {
service::Roles::LIGHT =>
run_until_exit(
runtime,
service::new_light::<R, D, E>(config).map_err(|e| format!("{:?}", e))?,
exit.into_exit(),
),
_ => run_until_exit(
runtime,
service::new_full(config).map_err(|e| format!("{:?}", e))?,
worker
service::new_full::<R, D, E>(config).map_err(|e| format!("{:?}", e))?,
exit.into_exit(),
),
}.map_err(|e| format!("{:?}", e))
}),
cli::ParseAndPrepare::BuildSpec(cmd) => cmd.run::<NoCustom, _, _, _>(load_spec),
cli::ParseAndPrepare::ExportBlocks(cmd) => cmd.run_with_builder::<(), _, _, _, _, _, _>(|config|
Ok(service::new_chain_ops(config)?), load_spec, worker),
cli::ParseAndPrepare::ImportBlocks(cmd) => cmd.run_with_builder::<(), _, _, _, _, _, _>(|config|
Ok(service::new_chain_ops(config)?), load_spec, worker),
cli::ParseAndPrepare::CheckBlock(cmd) => cmd.run_with_builder::<(), _, _, _, _, _, _>(|config|
Ok(service::new_chain_ops(config)?), load_spec, worker),
cli::ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec),
cli::ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder::<(), _, _, _, _, _>(|config|
Ok(service::new_chain_ops(config)?), load_spec),
cli::ParseAndPrepare::CustomCommand(PolkadotSubCommands::ValidationWorker(args)) => {
if cfg!(feature = "browser") {
Err(error::Error::Input("Cannot run validation worker in browser".into()))
} else {
#[cfg(not(feature = "browser"))]
service::run_validation_worker(&args.mem_id)?;
Ok(())
}.map_err(|e| format!("{:?}", e))
}),
cli::ParseAndPrepare::BuildSpec(cmd) => cmd.run::<NoCustom, _, _, _>(&load_spec),
cli::ParseAndPrepare::ExportBlocks(cmd) => cmd.run_with_builder::<_, _, _, _, _, _, _>(|config|
Ok(service::new_chain_ops::<R, D, E>(config)?), &load_spec, exit),
cli::ParseAndPrepare::ImportBlocks(cmd) => cmd.run_with_builder::<_, _, _, _, _, _, _>(|config|
Ok(service::new_chain_ops::<R, D, E>(config)?), &load_spec, exit),
cli::ParseAndPrepare::CheckBlock(cmd) => cmd.run_with_builder::<_, _, _, _, _, _, _>(|config|
Ok(service::new_chain_ops::<R, D, E>(config)?), &load_spec, exit),
cli::ParseAndPrepare::PurgeChain(cmd) => cmd.run(&load_spec),
cli::ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder::<_, _, _, _, _, _>(|config|
Ok(service::new_chain_ops::<R, D, E>(config)?), &load_spec),
cli::ParseAndPrepare::CustomCommand(PolkadotSubCommands::ValidationWorker(args)) => {
if cfg!(feature = "browser") {
Err(error::Error::Input("Cannot run validation worker in browser".into()))
} else {
#[cfg(not(feature = "browser"))]
service::run_validation_worker(&args.mem_id)?;
Ok(())
}
}
}
}
}

fn run_until_exit<T, SC, B, CE, W>(
/// Run the given `service` using the `runtime` until it exits or `e` fires.
pub fn run_until_exit(
mut runtime: Runtime,
service: T,
worker: W,
) -> error::Result<()>
where
T: AbstractService<Block = service::Block, RuntimeApi = service::RuntimeApi,
SelectChain = SC, Backend = B, NetworkSpecialization = service::PolkadotProtocol, CallExecutor = CE>,
SC: service::SelectChain<service::Block> + 'static,
B: service::Backend<service::Block, service::Blake2Hasher> + 'static,
CE: service::CallExecutor<service::Block, service::Blake2Hasher> + Clone + Send + Sync + 'static,
W: Worker,
{
service: impl AbstractService,
e: impl Future<Output = ()> + Send + Unpin + 'static,
) -> error::Result<()> {
let (exit_send, exit) = oneshot::channel();

let executor = runtime.executor();
Expand All @@ -185,20 +189,21 @@ fn run_until_exit<T, SC, B, CE, W>(
// but we need to keep holding a reference to the global telemetry guard
let _telemetry = service.telemetry();

let work = worker.work(&service, WrappedExecutor(executor));
let service = service
.map_err(|err| error!("Error while running Service: {}", err))
.compat();
let future = select(service, work)
.map(|_| Ok::<_, ()>(()))
.compat();
let _ = runtime.block_on(future);
let service_res = {
let service = service
.map_err(|err| error::Error::Service(err))
.compat();
let select = select(service, e)
.map(|_| Ok(()))
.compat();
runtime.block_on(select)
};

let _ = exit_send.send(());

use futures01::Future;

// TODO [andre]: timeout this future substrate/#1318
let _ = runtime.shutdown_on_idle().wait();

Ok(())
service_res
}
4 changes: 2 additions & 2 deletions collator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ client = { package = "sc-client", git = "https://github.com/paritytech/substrate
client-api = { package = "sc-client-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
primitives = { package = "sp-core", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
consensus_common = { package = "sp-consensus", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
polkadot-runtime = { path = "../runtime" }
polkadot-primitives = { path = "../primitives" }
polkadot-cli = { path = "../cli" }
polkadot-network = { path = "../network" }
polkadot-validation = { path = "../validation" }
polkadot-service = { path = "../service" }
log = "0.4.8"
tokio = "0.2.1"
tokio = "0.1.22"
futures-timer = "1.0"

[dev-dependencies]
Expand Down
Loading

0 comments on commit 9ff8c3a

Please sign in to comment.