123456789use std::sync::Arc;101112use nft_runtime::RuntimeApi;131415use cumulus_client_consensus_aura::{16 build_aura_consensus, BuildAuraConsensusParams, SlotProportion,17};18use cumulus_client_consensus_common::ParachainConsensus;19use cumulus_client_network::build_block_announce_validator;20use cumulus_client_service::{21 prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams,22};23use cumulus_primitives_core::ParaId;242526use polkadot_primitives::v1::CollatorPair;272829use sc_client_api::ExecutorProvider;30pub use sc_executor::NativeExecutor;31use sc_executor::native_executor_instance;32use sc_network::NetworkService;33use sc_service::{Configuration, PartialComponents, Role, TFullBackend, TFullClient, TaskManager};34use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle};35use sp_api::ConstructRuntimeApi;36use sp_consensus::SlotData;37use sp_keystore::SyncCryptoStorePtr;38use sp_runtime::traits::BlakeTwo256;39use substrate_prometheus_endpoint::Registry;404142type BlockNumber = u32;43type Header = sp_runtime::generic::Header<BlockNumber, sp_runtime::traits::BlakeTwo256>;44pub type Block = sp_runtime::generic::Block<Header, sp_runtime::OpaqueExtrinsic>;45type Hash = sp_core::H256;464748native_executor_instance!(49 pub ParachainRuntimeExecutor,50 nft_runtime::api::dispatch,51 nft_runtime::native_version,52 frame_benchmarking::benchmarking::HostFunctions,53);545556575859pub fn new_partial<RuntimeApi, Executor, BIQ>(60 config: &Configuration,61 build_import_queue: BIQ,62) -> Result<63 PartialComponents<64 TFullClient<Block, RuntimeApi, Executor>,65 TFullBackend<Block>,66 (),67 sp_consensus::DefaultImportQueue<Block, TFullClient<Block, RuntimeApi, Executor>>,68 sc_transaction_pool::FullPool<Block, TFullClient<Block, RuntimeApi, Executor>>,69 (Option<Telemetry>, Option<TelemetryWorkerHandle>),70 >,71 sc_service::Error,72>73where74 RuntimeApi: ConstructRuntimeApi<Block, TFullClient<Block, RuntimeApi, Executor>>75 + Send76 + Sync77 + 'static,78 RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>79 + sp_api::Metadata<Block>80 + sp_session::SessionKeys<Block>81 + sp_api::ApiExt<82 Block,83 StateBackend = sc_client_api::StateBackendFor<TFullBackend<Block>, Block>,84 > + sp_offchain::OffchainWorkerApi<Block>85 + sp_block_builder::BlockBuilder<Block>,86 sc_client_api::StateBackendFor<TFullBackend<Block>, Block>: sp_api::StateBackend<BlakeTwo256>,87 Executor: sc_executor::NativeExecutionDispatch + 'static,88 BIQ: FnOnce(89 Arc<TFullClient<Block, RuntimeApi, Executor>>,90 &Configuration,91 Option<TelemetryHandle>,92 &TaskManager,93 ) -> Result<94 sp_consensus::DefaultImportQueue<Block, TFullClient<Block, RuntimeApi, Executor>>,95 sc_service::Error,96 >,97{98 let telemetry = config99 .telemetry_endpoints100 .clone()101 .filter(|x| !x.is_empty())102 .map(|endpoints| -> Result<_, sc_telemetry::Error> {103 let worker = TelemetryWorker::new(16)?;104 let telemetry = worker.handle().new_telemetry(endpoints);105 Ok((worker, telemetry))106 })107 .transpose()?;108109 let telemetry = config.telemetry_endpoints.clone()110 .filter(|x| !x.is_empty())111 .map(|endpoints| -> Result<_, sc_telemetry::Error> {112 let worker = TelemetryWorker::new(16)?;113 let telemetry = worker.handle().new_telemetry(endpoints);114 Ok((worker, telemetry))115 })116 .transpose()?;117118 let (client, backend, keystore_container, task_manager) =119 sc_service::new_full_parts::<Block, RuntimeApi, Executor>(120 &config,121 telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),122 )?;123 let client = Arc::new(client);124125 let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle());126127 let telemetry = telemetry.map(|(worker, telemetry)| {128 task_manager.spawn_handle().spawn("telemetry", worker.run());129 telemetry130 });131132 let transaction_pool = sc_transaction_pool::BasicPool::new_full(133 config.transaction_pool.clone(),134 config.role.is_authority().into(),135 config.prometheus_registry(),136 task_manager.spawn_handle(),137 client.clone(),138 );139140 let import_queue = build_import_queue(141 client.clone(),142 config,143 telemetry.as_ref().map(|telemetry| telemetry.handle()),144 &task_manager,145 )?;146147 let params = PartialComponents {148 backend,149 client,150 import_queue,151 keystore_container,152 task_manager,153 transaction_pool,154 select_chain: (),155 other: (telemetry, telemetry_worker_handle),156 };157158 Ok(params)159}160161162163164#[sc_tracing::logging::prefix_logs_with("Parachain")]165async fn start_node_impl<RuntimeApi, Executor, RB, BIQ, BIC>(166 parachain_config: Configuration,167 collator_key: CollatorPair,168 polkadot_config: Configuration,169 id: ParaId,170 rpc_ext_builder: RB,171 build_import_queue: BIQ,172 build_consensus: BIC,173) -> sc_service::error::Result<(TaskManager, Arc<TFullClient<Block, RuntimeApi, Executor>>)>174where175 RuntimeApi: ConstructRuntimeApi<Block, TFullClient<Block, RuntimeApi, Executor>>176 + Send177 + Sync178 + 'static,179 RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>180 + sp_api::Metadata<Block>181 + sp_session::SessionKeys<Block>182 + sp_api::ApiExt<183 Block,184 StateBackend = sc_client_api::StateBackendFor<TFullBackend<Block>, Block>,185 > + sp_offchain::OffchainWorkerApi<Block>186 + sp_block_builder::BlockBuilder<Block>187 + cumulus_primitives_core::CollectCollationInfo<Block>,188 sc_client_api::StateBackendFor<TFullBackend<Block>, Block>: sp_api::StateBackend<BlakeTwo256>,189 Executor: sc_executor::NativeExecutionDispatch + 'static,190 RB: Fn(191 Arc<TFullClient<Block, RuntimeApi, Executor>>,192 ) -> jsonrpc_core::IoHandler<sc_rpc::Metadata>193 + Send194 + 'static,195 BIQ: FnOnce(196 Arc<TFullClient<Block, RuntimeApi, Executor>>,197 &Configuration,198 Option<TelemetryHandle>,199 &TaskManager,200 ) -> Result<201 sp_consensus::DefaultImportQueue<Block, TFullClient<Block, RuntimeApi, Executor>>,202 sc_service::Error,203 >,204 BIC: FnOnce(205 Arc<TFullClient<Block, RuntimeApi, Executor>>,206 Option<&Registry>,207 Option<TelemetryHandle>,208 &TaskManager,209 &polkadot_service::NewFull<polkadot_service::Client>,210 Arc<sc_transaction_pool::FullPool<Block, TFullClient<Block, RuntimeApi, Executor>>>,211 Arc<NetworkService<Block, Hash>>,212 SyncCryptoStorePtr,213 bool,214 ) -> Result<Box<dyn ParachainConsensus<Block>>, sc_service::Error>,215{216 if matches!(parachain_config.role, Role::Light) {217 return Err("Light client not supported!".into());218 }219220 let parachain_config = prepare_node_config(parachain_config);221222 let params = new_partial::<RuntimeApi, Executor, BIQ>(¶chain_config, build_import_queue)?;223 let (mut telemetry, telemetry_worker_handle) = params.other;224225 let relay_chain_full_node = cumulus_client_service::build_polkadot_full_node(226 polkadot_config,227 collator_key.clone(),228 telemetry_worker_handle,229 )230 .map_err(|e| match e {231 polkadot_service::Error::Sub(x) => x,232 s => format!("{}", s).into(),233 })?;234235 let client = params.client.clone();236 let backend = params.backend.clone();237 let block_announce_validator = build_block_announce_validator(238 relay_chain_full_node.client.clone(),239 id,240 Box::new(relay_chain_full_node.network.clone()),241 relay_chain_full_node.backend.clone(),242 );243244 let force_authoring = parachain_config.force_authoring;245 let validator = parachain_config.role.is_authority();246 let prometheus_registry = parachain_config.prometheus_registry().cloned();247 let transaction_pool = params.transaction_pool.clone();248 let mut task_manager = params.task_manager;249 let import_queue = cumulus_client_service::SharedImportQueue::new(params.import_queue);250 let (network, network_status_sinks, system_rpc_tx, start_network) =251 sc_service::build_network(sc_service::BuildNetworkParams {252 config: ¶chain_config,253 client: client.clone(),254 transaction_pool: transaction_pool.clone(),255 spawn_handle: task_manager.spawn_handle(),256 import_queue: import_queue.clone(),257 on_demand: None,258 block_announce_validator_builder: Some(Box::new(|_| block_announce_validator)),259 })?;260261 let rpc_client = client.clone();262 let rpc_extensions_builder = Box::new(move |_, _| rpc_ext_builder(rpc_client.clone()));263264 sc_service::spawn_tasks(sc_service::SpawnTasksParams {265 on_demand: None,266 remote_blockchain: None,267 rpc_extensions_builder,268 client: client.clone(),269 transaction_pool: transaction_pool.clone(),270 task_manager: &mut task_manager,271 config: parachain_config,272 keystore: params.keystore_container.sync_keystore(),273 backend: backend.clone(),274 network: network.clone(),275 network_status_sinks,276 system_rpc_tx,277 telemetry: telemetry.as_mut(),278 })?;279280 let announce_block = {281 let network = network.clone();282 Arc::new(move |hash, data| network.announce_block(hash, data))283 };284285 if validator {286 let parachain_consensus = build_consensus(287 client.clone(),288 prometheus_registry.as_ref(),289 telemetry.as_ref().map(|t| t.handle()),290 &task_manager,291 &relay_chain_full_node,292 transaction_pool,293 network,294 params.keystore_container.sync_keystore(),295 force_authoring,296 )?;297298 let spawner = task_manager.spawn_handle();299300 let params = StartCollatorParams {301 para_id: id,302 block_status: client.clone(),303 announce_block,304 client: client.clone(),305 task_manager: &mut task_manager,306 collator_key,307 relay_chain_full_node,308 spawner,309 parachain_consensus,310 import_queue,311 };312313 start_collator(params).await?;314 } else {315 let params = StartFullNodeParams {316 client: client.clone(),317 announce_block,318 task_manager: &mut task_manager,319 para_id: id,320 relay_chain_full_node,321 };322323 start_full_node(params)?;324 }325326 start_network.start_network();327328 Ok((task_manager, client))329}330331332pub fn parachain_build_import_queue(333 client: Arc<TFullClient<Block, RuntimeApi, ParachainRuntimeExecutor>>,334 config: &Configuration,335 telemetry: Option<TelemetryHandle>,336 task_manager: &TaskManager,337) -> Result<338 sp_consensus::DefaultImportQueue<339 Block,340 TFullClient<Block, RuntimeApi, ParachainRuntimeExecutor>,341 >,342 sc_service::Error,343> {344 let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;345346347 cumulus_client_consensus_aura::import_queue::<348 sp_consensus_aura::sr25519::AuthorityPair,349 _,350 _,351 _,352 _,353 _,354 _,355 >(cumulus_client_consensus_aura::ImportQueueParams {356 block_import: client.clone(),357 client: client.clone(),358 create_inherent_data_providers: move |_, _| async move {359 let time = sp_timestamp::InherentDataProvider::from_system_time();360361 let slot =362 sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(363 *time,364 slot_duration.slot_duration(),365 );366367 Ok((time, slot))368 },369 registry: config.prometheus_registry().clone(),370 can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),371 spawner: &task_manager.spawn_essential_handle(),372 telemetry,373 })374 .map_err(Into::into)375}376377378pub async fn start_node(379 parachain_config: Configuration,380 collator_key: CollatorPair,381 polkadot_config: Configuration,382 id: ParaId,383) -> sc_service::error::Result<(TaskManager, Arc<TFullClient<Block, RuntimeApi, ParachainRuntimeExecutor>>)> {384 start_node_impl::<RuntimeApi, ParachainRuntimeExecutor, _, _, _>(385 parachain_config,386 collator_key,387 polkadot_config,388 id,389 |_| Default::default(),390 parachain_build_import_queue,391 |client,392 prometheus_registry,393 telemetry,394 task_manager,395 relay_chain_node,396 transaction_pool,397 sync_oracle,398 keystore,399 force_authoring| {400 let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;401402 let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(403 task_manager.spawn_handle(),404 client.clone(),405 transaction_pool,406 prometheus_registry.clone(),407 telemetry.clone(),408 );409410 let relay_chain_backend = relay_chain_node.backend.clone();411 let relay_chain_client = relay_chain_node.client.clone();412 Ok(build_aura_consensus::<413 sp_consensus_aura::sr25519::AuthorityPair,414 _,415 _,416 _,417 _,418 _,419 _,420 _,421 _,422 _,423 >(BuildAuraConsensusParams {424 proposer_factory,425 create_inherent_data_providers: move |_, (relay_parent, validation_data)| {426 let parachain_inherent =427 cumulus_primitives_parachain_inherent::ParachainInherentData::create_at_with_client(428 relay_parent,429 &relay_chain_client,430 &*relay_chain_backend,431 &validation_data,432 id,433 );434 async move {435 let time = sp_timestamp::InherentDataProvider::from_system_time();436437 let slot =438 sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(439 *time,440 slot_duration.slot_duration(),441 );442443 let parachain_inherent = parachain_inherent.ok_or_else(|| {444 Box::<dyn std::error::Error + Send + Sync>::from(445 "Failed to create parachain inherent",446 )447 })?;448 Ok((time, slot, parachain_inherent))449 }450 },451 block_import: client.clone(),452 relay_chain_client: relay_chain_node.client.clone(),453 relay_chain_backend: relay_chain_node.backend.clone(),454 para_client: client.clone(),455 backoff_authoring_blocks: Option::<()>::None,456 sync_oracle,457 keystore,458 force_authoring,459 slot_duration,460 461 block_proposal_slot_portion: SlotProportion::new(1f32 / 24f32),462 telemetry,463 }))464 },465 )466 .await467}