Add canvas-kusama runtime (#980)

* Added kanvas runtime

* Fix up benchmarking

* Fixup markdown stucture

* replace :emoji_name: by utf8
* fix up header hierarchy

* Merge canvas README

* Only use "Canvas" as a name

* Remove reference to Rocanvas
This commit is contained in:
Alexander Theißen
2022-02-17 22:18:48 +01:00
committed by GitHub
parent eeca2bb61a
commit 4d319d0fae
13 changed files with 3174 additions and 295 deletions
@@ -834,3 +834,254 @@ fn westmint_genesis(
},
}
}
/// We use the same runtime on kusama and rococo.
pub type CanvasKusamaChainSpec =
sc_service::GenericChainSpec<canvas_kusama_runtime::GenesisConfig, Extensions>;
/// No relay chain suffix because the id is the same over all relay chains.
const CANVAS_PARACHAIN_ID: u32 = 1002;
/// The existential deposit is determined by the runtime "canvas-kusama".
const CANVAS_KUSAMA_ED: canvas_kusama_runtime::Balance =
canvas_kusama_runtime::constants::currency::EXISTENTIAL_DEPOSIT;
pub fn canvas_rococo_development_config() -> CanvasKusamaChainSpec {
let mut properties = sc_chain_spec::Properties::new();
properties.insert("tokenSymbol".into(), "ROC".into());
properties.insert("tokenDecimals".into(), 12.into());
CanvasKusamaChainSpec::from_genesis(
// Name
"Canvas on Rococo Development",
// ID
"canvas-rococo-dev",
ChainType::Development,
move || {
canvas_kusama_genesis(
// initial collators.
vec![
(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_collator_keys_from_seed::<canvas_kusama_runtime::AuraId>("Alice"),
),
(
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_collator_keys_from_seed::<canvas_kusama_runtime::AuraId>("Bob"),
),
],
vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_account_id_from_seed::<sr25519::Public>("Charlie"),
get_account_id_from_seed::<sr25519::Public>("Dave"),
get_account_id_from_seed::<sr25519::Public>("Eve"),
get_account_id_from_seed::<sr25519::Public>("Ferdie"),
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
],
CANVAS_PARACHAIN_ID.into(),
)
},
Vec::new(),
None,
None,
None,
None,
Extensions {
relay_chain: "rococo-local".into(), // You MUST set this to the correct network!
para_id: CANVAS_PARACHAIN_ID,
},
)
}
pub fn canvas_rococo_local_config() -> CanvasKusamaChainSpec {
let mut properties = sc_chain_spec::Properties::new();
properties.insert("tokenSymbol".into(), "ROC".into());
properties.insert("tokenDecimals".into(), 12.into());
CanvasKusamaChainSpec::from_genesis(
// Name
"Canvas on Rococo",
// ID
"canvas-rococo-local",
ChainType::Local,
move || {
canvas_kusama_genesis(
// initial collators.
vec![
(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_collator_keys_from_seed::<canvas_kusama_runtime::AuraId>("Alice"),
),
(
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_collator_keys_from_seed::<canvas_kusama_runtime::AuraId>("Bob"),
),
],
vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_account_id_from_seed::<sr25519::Public>("Charlie"),
get_account_id_from_seed::<sr25519::Public>("Dave"),
get_account_id_from_seed::<sr25519::Public>("Eve"),
get_account_id_from_seed::<sr25519::Public>("Ferdie"),
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
],
CANVAS_PARACHAIN_ID.into(),
)
},
// Bootnodes
Vec::new(),
// Telemetry
None,
// Protocol ID
None,
// Fork ID
None,
// Properties
Some(properties),
// Extensions
Extensions {
relay_chain: "rococo-local".into(), // You MUST set this to the correct network!
para_id: CANVAS_PARACHAIN_ID,
},
)
}
pub fn canvas_rococo_config() -> CanvasKusamaChainSpec {
// Give your base currency a unit name and decimal places
let mut properties = sc_chain_spec::Properties::new();
properties.insert("tokenSymbol".into(), "ROC".into());
properties.insert("tokenDecimals".into(), 12.into());
CanvasKusamaChainSpec::from_genesis(
// Name
"Canvas on Rococo",
// ID
"canvas-rococo",
ChainType::Live,
move || {
canvas_kusama_genesis(
vec![
// 5GKFbTTgrVS4Vz1UWWHPqMZQNFWZtqo7H2KpCDyYhEL3aS26
(
hex!["bc09354c12c054c8f6b3da208485eacec4ac648bad348895273b37bab5a0937c"]
.into(),
hex!["bc09354c12c054c8f6b3da208485eacec4ac648bad348895273b37bab5a0937c"]
.unchecked_into(),
),
// 5EPRJHm2GpABVWcwnAujcrhnrjFZyDGd5TwKFzkBoGgdRyv2
(
hex!["66be63b7bcbfb91040e5248e2d1ceb822cf219c57848c5924ffa3a1f8e67ba72"]
.into(),
hex!["66be63b7bcbfb91040e5248e2d1ceb822cf219c57848c5924ffa3a1f8e67ba72"]
.unchecked_into(),
),
// 5GH62vrJrVZxLREcHzm2PR5uTLAT5RQMJitoztCGyaP4o3uM
(
hex!["ba62886472a0a9f66b5e39f1469ce1c5b3d8cad6be39078daf16f111e89d1e44"]
.into(),
hex!["ba62886472a0a9f66b5e39f1469ce1c5b3d8cad6be39078daf16f111e89d1e44"]
.unchecked_into(),
),
// 5FHfoJDLdjRYX5KXLRqMDYBbWrwHLMtti21uK4QByUoUAbJF
(
hex!["8e97f65cda001976311df9bed39e8d0c956089093e94a75ef76fe9347a0eda7b"]
.into(),
hex!["8e97f65cda001976311df9bed39e8d0c956089093e94a75ef76fe9347a0eda7b"]
.unchecked_into(),
),
],
// Warning: The configuration for a production chain should not contain
// any endowed accounts here, otherwise it'll be minting extra native tokens
// from the relay chain on the parachain.
vec![
// NOTE: Remove endowed accounts if deployed on other relay chains.
// Endowed accounts
hex!["baa78c7154c7f82d6d377177e20bcab65d327eca0086513f9964f5a0f6bdad56"].into(),
// AccountId of an account which `ink-waterfall` uses for automated testing
hex!["0e47e2344d523c3cc5c34394b0d58b9a4200e813a038e6c5a6163cc07d70b069"].into(),
],
CANVAS_PARACHAIN_ID.into(),
)
},
// Bootnodes
vec![
"/ip4/34.90.191.237/tcp/30333/p2p/12D3KooWKg3Rpxcr9oJ8n6khoxpGKWztCZydtUZk2cojHqnfLrpj"
.parse()
.expect("MultiaddrWithPeerId"),
"/ip4/35.204.68.28/tcp/30333/p2p/12D3KooWPEXYrz8tHU3nDtPoPw4V7ou5dzMEWSTuUj7vaWiYVAVh"
.parse()
.expect("MultiaddrWithPeerId"),
"/ip4/34.90.139.15/tcp/30333/p2p/12D3KooWEVU8AFNary4nP4qEnEcwJaRuy59Wefekzdu9pKbnVEhk"
.parse()
.expect("MultiaddrWithPeerId"),
"/ip4/35.204.99.97/tcp/30333/p2p/12D3KooWP6pV3ZmcXzGDjv8ZMgA6nZxfAKDxSz4VNiLx6vVCQgJX"
.parse()
.expect("MultiaddrWithPeerId"),
],
// Telemetry
None,
// Protocol ID
None,
// Fork ID
None,
// Properties
Some(properties),
// Extensions
Extensions { relay_chain: "rococo".into(), para_id: CANVAS_PARACHAIN_ID },
)
}
fn canvas_kusama_genesis(
invulnerables: Vec<(AccountId, AuraId)>,
endowed_accounts: Vec<AccountId>,
id: ParaId,
) -> canvas_kusama_runtime::GenesisConfig {
canvas_kusama_runtime::GenesisConfig {
system: canvas_kusama_runtime::SystemConfig {
code: canvas_kusama_runtime::WASM_BINARY
.expect("WASM binary was not build, please build it!")
.to_vec(),
},
balances: canvas_kusama_runtime::BalancesConfig {
balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(),
},
parachain_info: canvas_kusama_runtime::ParachainInfoConfig { parachain_id: id },
collator_selection: canvas_kusama_runtime::CollatorSelectionConfig {
invulnerables: invulnerables.iter().cloned().map(|(acc, _)| acc).collect(),
candidacy_bond: CANVAS_KUSAMA_ED * 16,
..Default::default()
},
session: canvas_kusama_runtime::SessionConfig {
keys: invulnerables
.into_iter()
.map(|(acc, aura)| {
(
acc.clone(), // account id
acc, // validator id
canvas_kusama_runtime::SessionKeys { aura }, // session keys
)
})
.collect(),
},
// no need to pass anything to aura, in fact it will panic if we do. Session will take care
// of this.
aura: Default::default(),
aura_ext: Default::default(),
parachain_system: Default::default(),
polkadot_xcm: canvas_kusama_runtime::PolkadotXcmConfig {
safe_xcm_version: Some(SAFE_XCM_VERSION),
},
}
}
+33 -3
View File
@@ -18,9 +18,9 @@ use crate::{
chain_spec,
cli::{Cli, RelayChainCli, Subcommand},
service::{
new_partial, Block, RococoParachainRuntimeExecutor, SeedlingRuntimeExecutor,
ShellRuntimeExecutor, StatemineRuntimeExecutor, StatemintRuntimeExecutor,
WestmintRuntimeExecutor,
new_partial, Block, CanvasKusamaRuntimeExecutor, RococoParachainRuntimeExecutor,
SeedlingRuntimeExecutor, ShellRuntimeExecutor, StatemineRuntimeExecutor,
StatemintRuntimeExecutor, WestmintRuntimeExecutor,
},
};
use codec::Encode;
@@ -47,6 +47,7 @@ trait IdentifyChain {
fn is_statemint(&self) -> bool;
fn is_statemine(&self) -> bool;
fn is_westmint(&self) -> bool;
fn is_canvas_kusama(&self) -> bool;
}
impl IdentifyChain for dyn sc_service::ChainSpec {
@@ -65,6 +66,10 @@ impl IdentifyChain for dyn sc_service::ChainSpec {
fn is_westmint(&self) -> bool {
self.id().starts_with("westmint")
}
fn is_canvas_kusama(&self) -> bool {
// we use the same runtime on rococo and kusama
self.id().starts_with("canvas-kusama") || self.id().starts_with("canvas-rococo")
}
}
impl<T: sc_service::ChainSpec + 'static> IdentifyChain for T {
@@ -83,6 +88,9 @@ impl<T: sc_service::ChainSpec + 'static> IdentifyChain for T {
fn is_westmint(&self) -> bool {
<dyn sc_service::ChainSpec>::is_westmint(self)
}
fn is_canvas_kusama(&self) -> bool {
<dyn sc_service::ChainSpec>::is_canvas_kusama(self)
}
}
fn load_spec(id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
@@ -126,6 +134,10 @@ fn load_spec(id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, St
"westmint" => Box::new(chain_spec::ChainSpec::from_json_bytes(
&include_bytes!("../res/westmint.json")[..],
)?),
// -- Canvas on Rococo
"canvas-rococo-dev" => Box::new(chain_spec::canvas_rococo_development_config()),
"canvas-rococo-local" => Box::new(chain_spec::canvas_rococo_local_config()),
"canvas-rococo" => Box::new(chain_spec::canvas_rococo_config()),
"" => Box::new(chain_spec::get_chain_spec()),
path => {
let chain_spec = chain_spec::ChainSpec::from_json_file(path.into())?;
@@ -139,6 +151,8 @@ fn load_spec(id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, St
Box::new(chain_spec::ShellChainSpec::from_json_file(path.into())?)
} else if chain_spec.is_seedling() {
Box::new(chain_spec::SeedlingChainSpec::from_json_file(path.into())?)
} else if chain_spec.is_canvas_kusama() {
Box::new(chain_spec::CanvasKusamaChainSpec::from_json_file(path.into())?)
} else {
Box::new(chain_spec)
}
@@ -192,6 +206,8 @@ impl SubstrateCli for Cli {
&shell_runtime::VERSION
} else if chain_spec.is_seedling() {
&seedling_runtime::VERSION
} else if chain_spec.is_canvas_kusama() {
&canvas_kusama_runtime::VERSION
} else {
&rococo_parachain_runtime::VERSION
}
@@ -296,6 +312,15 @@ macro_rules! construct_async_run {
let task_manager = $components.task_manager;
{ $( $code )* }.map(|v| (v, task_manager))
})
} else if runner.config().chain_spec.is_canvas_kusama() {
runner.async_run(|$config| {
let $components = new_partial::<canvas_kusama_runtime::RuntimeApi, CanvasKusamaRuntimeExecutor, _>(
&$config,
crate::service::canvas_kusama_build_import_queue,
)?;
let task_manager = $components.task_manager;
{ $( $code )* }.map(|v| (v, task_manager))
})
} else {
runner.async_run(|$config| {
let $components = new_partial::<
@@ -542,6 +567,11 @@ pub fn run() -> Result<()> {
.await
.map(|r| r.0)
.map_err(Into::into)
} else if config.chain_spec.is_canvas_kusama() {
crate::service::start_canvas_kusama_node(config, polkadot_config, id)
.await
.map(|r| r.0)
.map_err(Into::into)
} else {
crate::service::start_rococo_parachain_node(config, polkadot_config, id)
.await
+31 -2
View File
@@ -20,6 +20,8 @@
use std::sync::Arc;
use pallet_contracts_rpc::{Contracts, ContractsApi};
use parachains_common::{AccountId, Balance, Block, BlockNumber, Hash, Index as Nonce};
use sc_client_api::AuxStore;
pub use sc_rpc::{DenyUnsafe, SubscriptionTaskExecutor};
use sc_transaction_pool_api::TransactionPool;
@@ -27,8 +29,6 @@ use sp_api::ProvideRuntimeApi;
use sp_block_builder::BlockBuilder;
use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
use parachains_common::{AccountId, Balance, Block, Index as Nonce};
/// A type representing all RPC extensions.
pub type RpcExtension = jsonrpc_core::IoHandler<sc_rpc::Metadata>;
@@ -68,3 +68,32 @@ where
io
}
/// Instantiate all RPCs we want at the canvas-kusama chain.
pub fn create_canvas_kusama<C, P>(deps: FullDeps<C, P>) -> RpcExtension
where
C: ProvideRuntimeApi<Block>
+ HeaderBackend<Block>
+ AuxStore
+ HeaderMetadata<Block, Error = BlockChainError>
+ Send
+ Sync
+ 'static,
C::Api: frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>,
C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>,
C::Api: pallet_contracts_rpc::ContractsRuntimeApi<Block, AccountId, Balance, BlockNumber, Hash>,
C::Api: BlockBuilder<Block>,
P: TransactionPool + Sync + Send + 'static,
{
use frame_rpc_system::{FullSystem, SystemApi};
use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi};
let mut io = jsonrpc_core::IoHandler::default();
let FullDeps { client, pool, deny_unsafe } = deps;
io.extend_with(SystemApi::to_delegate(FullSystem::new(client.clone(), pool, deny_unsafe)));
io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(client.clone())));
io.extend_with(ContractsApi::to_delegate(Contracts::new(client)));
io
}
+354 -1
View File
@@ -32,7 +32,7 @@ use cumulus_relay_chain_local::build_relay_chain_interface;
use polkadot_service::NativeExecutionDispatch;
use crate::rpc;
pub use parachains_common::{AccountId, Balance, Block, Hash, Header, Index as Nonce};
pub use parachains_common::{AccountId, Balance, Block, BlockNumber, Hash, Header, Index as Nonce};
use cumulus_client_consensus_relay_chain::Verifier as RelayChainVerifier;
use futures::lock::Mutex;
@@ -148,6 +148,21 @@ impl sc_executor::NativeExecutionDispatch for WestmintRuntimeExecutor {
}
}
/// Native Canvas on Kusama executor instance.
pub struct CanvasKusamaRuntimeExecutor;
impl sc_executor::NativeExecutionDispatch for CanvasKusamaRuntimeExecutor {
type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
canvas_kusama_runtime::api::dispatch(method, data)
}
fn native_version() -> sc_executor::NativeVersion {
canvas_kusama_runtime::native_version()
}
}
/// Starts a `ServiceBuilder` for a full service.
///
/// Use this macro if you don't actually need the full service, but just the builder in order to
@@ -1252,3 +1267,341 @@ where
)
.await
}
#[sc_tracing::logging::prefix_logs_with("Parachain")]
async fn start_canvas_kusama_node_impl<RuntimeApi, Executor, RB, BIQ, BIC>(
parachain_config: Configuration,
polkadot_config: Configuration,
id: ParaId,
_rpc_ext_builder: RB,
build_import_queue: BIQ,
build_consensus: BIC,
) -> sc_service::error::Result<(
TaskManager,
Arc<TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>,
)>
where
RuntimeApi: ConstructRuntimeApi<Block, TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>
+ Send
+ Sync
+ 'static,
RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
+ sp_api::Metadata<Block>
+ sp_session::SessionKeys<Block>
+ sp_api::ApiExt<
Block,
StateBackend = sc_client_api::StateBackendFor<TFullBackend<Block>, Block>,
> + sp_offchain::OffchainWorkerApi<Block>
+ sp_block_builder::BlockBuilder<Block>
+ cumulus_primitives_core::CollectCollationInfo<Block>
+ pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>
+ frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>
+ pallet_contracts_rpc::ContractsRuntimeApi<Block, AccountId, Balance, BlockNumber, Hash>,
sc_client_api::StateBackendFor<TFullBackend<Block>, Block>: sp_api::StateBackend<BlakeTwo256>,
Executor: sc_executor::NativeExecutionDispatch + 'static,
RB: Fn(
Arc<TFullClient<Block, RuntimeApi, Executor>>,
) -> Result<jsonrpc_core::IoHandler<sc_rpc::Metadata>, sc_service::Error>
+ Send
+ 'static,
BIQ: FnOnce(
Arc<TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>,
&Configuration,
Option<TelemetryHandle>,
&TaskManager,
) -> Result<
sc_consensus::DefaultImportQueue<
Block,
TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>,
>,
sc_service::Error,
> + 'static,
BIC: FnOnce(
Arc<TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>>,
Option<&Registry>,
Option<TelemetryHandle>,
&TaskManager,
Arc<dyn RelayChainInterface>,
Arc<
sc_transaction_pool::FullPool<
Block,
TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<Executor>>,
>,
>,
Arc<NetworkService<Block, Hash>>,
SyncCryptoStorePtr,
bool,
) -> Result<Box<dyn ParachainConsensus<Block>>, sc_service::Error>,
{
if matches!(parachain_config.role, Role::Light) {
return Err("Light client not supported!".into())
}
let parachain_config = prepare_node_config(parachain_config);
let params = new_partial::<RuntimeApi, Executor, BIQ>(&parachain_config, build_import_queue)?;
let (mut telemetry, telemetry_worker_handle) = params.other;
let client = params.client.clone();
let backend = params.backend.clone();
let mut task_manager = params.task_manager;
let (relay_chain_interface, collator_key) =
build_relay_chain_interface(polkadot_config, telemetry_worker_handle, &mut task_manager)
.map_err(|e| match e {
polkadot_service::Error::Sub(x) => x,
s => format!("{}", s).into(),
})?;
let block_announce_validator = BlockAnnounceValidator::new(relay_chain_interface.clone(), id);
let force_authoring = parachain_config.force_authoring;
let validator = parachain_config.role.is_authority();
let prometheus_registry = parachain_config.prometheus_registry().cloned();
let transaction_pool = params.transaction_pool.clone();
let import_queue = cumulus_client_service::SharedImportQueue::new(params.import_queue);
let (network, system_rpc_tx, start_network) =
sc_service::build_network(sc_service::BuildNetworkParams {
config: &parachain_config,
client: client.clone(),
transaction_pool: transaction_pool.clone(),
spawn_handle: task_manager.spawn_handle(),
import_queue: import_queue.clone(),
block_announce_validator_builder: Some(Box::new(|_| {
Box::new(block_announce_validator)
})),
warp_sync: None,
})?;
let rpc_extensions_builder = {
let client = client.clone();
let transaction_pool = transaction_pool.clone();
Box::new(move |deny_unsafe, _| {
let deps = crate::rpc::FullDeps {
client: client.clone(),
pool: transaction_pool.clone(),
deny_unsafe,
};
Ok(crate::rpc::create_canvas_kusama(deps))
})
};
sc_service::spawn_tasks(sc_service::SpawnTasksParams {
rpc_extensions_builder,
client: client.clone(),
transaction_pool: transaction_pool.clone(),
task_manager: &mut task_manager,
config: parachain_config,
keystore: params.keystore_container.sync_keystore(),
backend: backend.clone(),
network: network.clone(),
system_rpc_tx,
telemetry: telemetry.as_mut(),
})?;
let announce_block = {
let network = network.clone();
Arc::new(move |hash, data| network.announce_block(hash, data))
};
let relay_chain_slot_duration = Duration::from_secs(6);
if validator {
let parachain_consensus = build_consensus(
client.clone(),
prometheus_registry.as_ref(),
telemetry.as_ref().map(|t| t.handle()),
&task_manager,
relay_chain_interface.clone(),
transaction_pool,
network,
params.keystore_container.sync_keystore(),
force_authoring,
)?;
let spawner = task_manager.spawn_handle();
let params = StartCollatorParams {
para_id: id,
block_status: client.clone(),
announce_block,
client: client.clone(),
task_manager: &mut task_manager,
relay_chain_interface,
spawner,
parachain_consensus,
import_queue,
collator_key,
relay_chain_slot_duration,
};
start_collator(params).await?;
} else {
let params = StartFullNodeParams {
client: client.clone(),
announce_block,
task_manager: &mut task_manager,
para_id: id,
relay_chain_interface,
relay_chain_slot_duration,
import_queue,
};
start_full_node(params)?;
}
start_network.start_network();
Ok((task_manager, client))
}
#[allow(clippy::type_complexity)]
pub fn canvas_kusama_build_import_queue(
client: Arc<
TFullClient<
Block,
canvas_kusama_runtime::RuntimeApi,
NativeElseWasmExecutor<CanvasKusamaRuntimeExecutor>,
>,
>,
config: &Configuration,
telemetry: Option<TelemetryHandle>,
task_manager: &TaskManager,
) -> Result<
sc_consensus::DefaultImportQueue<
Block,
TFullClient<
Block,
canvas_kusama_runtime::RuntimeApi,
NativeElseWasmExecutor<CanvasKusamaRuntimeExecutor>,
>,
>,
sc_service::Error,
> {
let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;
cumulus_client_consensus_aura::import_queue::<
sp_consensus_aura::sr25519::AuthorityPair,
_,
_,
_,
_,
_,
_,
>(cumulus_client_consensus_aura::ImportQueueParams {
block_import: client.clone(),
client: client.clone(),
create_inherent_data_providers: move |_, _| async move {
let time = sp_timestamp::InherentDataProvider::from_system_time();
let slot =
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(
*time,
slot_duration.slot_duration(),
);
Ok((time, slot))
},
registry: config.prometheus_registry(),
can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),
spawner: &task_manager.spawn_essential_handle(),
telemetry,
})
.map_err(Into::into)
}
/// Start a parachain node.
pub async fn start_canvas_kusama_node(
parachain_config: Configuration,
polkadot_config: Configuration,
id: ParaId,
) -> sc_service::error::Result<(
TaskManager,
Arc<
TFullClient<
Block,
canvas_kusama_runtime::RuntimeApi,
NativeElseWasmExecutor<CanvasKusamaRuntimeExecutor>,
>,
>,
)> {
start_canvas_kusama_node_impl::<
canvas_kusama_runtime::RuntimeApi,
CanvasKusamaRuntimeExecutor,
_,
_,
_,
>(
parachain_config,
polkadot_config,
id,
|_| Ok(Default::default()),
canvas_kusama_build_import_queue,
|client,
prometheus_registry,
telemetry,
task_manager,
relay_chain_interface,
transaction_pool,
sync_oracle,
keystore,
force_authoring| {
let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;
let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(
task_manager.spawn_handle(),
client.clone(),
transaction_pool,
prometheus_registry,
telemetry.clone(),
);
Ok(AuraConsensus::build::<sp_consensus_aura::sr25519::AuthorityPair, _, _, _, _, _, _>(
BuildAuraConsensusParams {
proposer_factory,
create_inherent_data_providers: move |_, (relay_parent, validation_data)| {
let relay_chain_interface = relay_chain_interface.clone();
async move {
let parachain_inherent =
cumulus_primitives_parachain_inherent::ParachainInherentData::create_at(
relay_parent,
&relay_chain_interface,
&validation_data,
id,
).await;
let time = sp_timestamp::InherentDataProvider::from_system_time();
let slot =
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(
*time,
slot_duration.slot_duration(),
);
let parachain_inherent = parachain_inherent.ok_or_else(|| {
Box::<dyn std::error::Error + Send + Sync>::from(
"Failed to create parachain inherent",
)
})?;
Ok((time, slot, parachain_inherent))
}
},
block_import: client.clone(),
para_client: client,
backoff_authoring_blocks: Option::<()>::None,
sync_oracle,
keystore,
force_authoring,
slot_duration,
// We got around 500ms for proposing
block_proposal_slot_portion: SlotProportion::new(1f32 / 24f32),
// And a maximum of 750ms if slots are skipped
max_block_proposal_slot_portion: Some(SlotProportion::new(1f32 / 16f32)),
telemetry,
},
))
},
)
.await
}