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 (client, backend, keystore_container, task_manager) =110 sc_service::new_full_parts::<Block, RuntimeApi, Executor>(111 &config,112 telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),113 )?;114 let client = Arc::new(client);115116 let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle());117118 let telemetry = telemetry.map(|(worker, telemetry)| {119 task_manager.spawn_handle().spawn("telemetry", worker.run());120 telemetry121 });122123 let transaction_pool = sc_transaction_pool::BasicPool::new_full(124 config.transaction_pool.clone(),125 config.role.is_authority().into(),126 config.prometheus_registry(),127 task_manager.spawn_handle(),128 client.clone(),129 );130131 let import_queue = build_import_queue(132 client.clone(),133 config,134 telemetry.as_ref().map(|telemetry| telemetry.handle()),135 &task_manager,136 )?;137138 let params = PartialComponents {139 backend,140 client,141 import_queue,142 keystore_container,143 task_manager,144 transaction_pool,145 select_chain: (),146 other: (telemetry, telemetry_worker_handle),147 };148149 Ok(params)150}151152153154155#[sc_tracing::logging::prefix_logs_with("Parachain")]156async fn start_node_impl<RuntimeApi, Executor, RB, BIQ, BIC>(157 parachain_config: Configuration,158 collator_key: CollatorPair,159 polkadot_config: Configuration,160 id: ParaId,161 rpc_ext_builder: RB,162 build_import_queue: BIQ,163 build_consensus: BIC,164) -> sc_service::error::Result<(TaskManager, Arc<TFullClient<Block, RuntimeApi, Executor>>)>165where166 RuntimeApi: ConstructRuntimeApi<Block, TFullClient<Block, RuntimeApi, Executor>>167 + Send168 + Sync169 + 'static,170 RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>171 + sp_api::Metadata<Block>172 + sp_session::SessionKeys<Block>173 + sp_api::ApiExt<174 Block,175 StateBackend = sc_client_api::StateBackendFor<TFullBackend<Block>, Block>,176 > + sp_offchain::OffchainWorkerApi<Block>177 + sp_block_builder::BlockBuilder<Block>178 + cumulus_primitives_core::CollectCollationInfo<Block>,179 sc_client_api::StateBackendFor<TFullBackend<Block>, Block>: sp_api::StateBackend<BlakeTwo256>,180 Executor: sc_executor::NativeExecutionDispatch + 'static,181 RB: Fn(182 Arc<TFullClient<Block, RuntimeApi, Executor>>,183 ) -> jsonrpc_core::IoHandler<sc_rpc::Metadata>184 + Send185 + 'static,186 BIQ: FnOnce(187 Arc<TFullClient<Block, RuntimeApi, Executor>>,188 &Configuration,189 Option<TelemetryHandle>,190 &TaskManager,191 ) -> Result<192 sp_consensus::DefaultImportQueue<Block, TFullClient<Block, RuntimeApi, Executor>>,193 sc_service::Error,194 >,195 BIC: FnOnce(196 Arc<TFullClient<Block, RuntimeApi, Executor>>,197 Option<&Registry>,198 Option<TelemetryHandle>,199 &TaskManager,200 &polkadot_service::NewFull<polkadot_service::Client>,201 Arc<sc_transaction_pool::FullPool<Block, TFullClient<Block, RuntimeApi, Executor>>>,202 Arc<NetworkService<Block, Hash>>,203 SyncCryptoStorePtr,204 bool,205 ) -> Result<Box<dyn ParachainConsensus<Block>>, sc_service::Error>,206{207 if matches!(parachain_config.role, Role::Light) {208 return Err("Light client not supported!".into());209 }210211 let parachain_config = prepare_node_config(parachain_config);212213 let params = new_partial::<RuntimeApi, Executor, BIQ>(¶chain_config, build_import_queue)?;214 let (mut telemetry, telemetry_worker_handle) = params.other;215216 let relay_chain_full_node = cumulus_client_service::build_polkadot_full_node(217 polkadot_config,218 collator_key.clone(),219 telemetry_worker_handle,220 )221 .map_err(|e| match e {222 polkadot_service::Error::Sub(x) => x,223 s => format!("{}", s).into(),224 })?;225226 let client = params.client.clone();227 let backend = params.backend.clone();228 let block_announce_validator = build_block_announce_validator(229 relay_chain_full_node.client.clone(),230 id,231 Box::new(relay_chain_full_node.network.clone()),232 relay_chain_full_node.backend.clone(),233 );234235 let force_authoring = parachain_config.force_authoring;236 let validator = parachain_config.role.is_authority();237 let prometheus_registry = parachain_config.prometheus_registry().cloned();238 let transaction_pool = params.transaction_pool.clone();239 let mut task_manager = params.task_manager;240 let import_queue = cumulus_client_service::SharedImportQueue::new(params.import_queue);241 let (network, network_status_sinks, system_rpc_tx, start_network) =242 sc_service::build_network(sc_service::BuildNetworkParams {243 config: ¶chain_config,244 client: client.clone(),245 transaction_pool: transaction_pool.clone(),246 spawn_handle: task_manager.spawn_handle(),247 import_queue: import_queue.clone(),248 on_demand: None,249 block_announce_validator_builder: Some(Box::new(|_| block_announce_validator)),250 })?;251252 let rpc_client = client.clone();253 let rpc_extensions_builder = Box::new(move |_, _| rpc_ext_builder(rpc_client.clone()));254255 sc_service::spawn_tasks(sc_service::SpawnTasksParams {256 on_demand: None,257 remote_blockchain: None,258 rpc_extensions_builder,259 client: client.clone(),260 transaction_pool: transaction_pool.clone(),261 task_manager: &mut task_manager,262 config: parachain_config,263 keystore: params.keystore_container.sync_keystore(),264 backend: backend.clone(),265 network: network.clone(),266 network_status_sinks,267 system_rpc_tx,268 telemetry: telemetry.as_mut(),269 })?;270271 let announce_block = {272 let network = network.clone();273 Arc::new(move |hash, data| network.announce_block(hash, data))274 };275276 if validator {277 let parachain_consensus = build_consensus(278 client.clone(),279 prometheus_registry.as_ref(),280 telemetry.as_ref().map(|t| t.handle()),281 &task_manager,282 &relay_chain_full_node,283 transaction_pool,284 network,285 params.keystore_container.sync_keystore(),286 force_authoring,287 )?;288289 let spawner = task_manager.spawn_handle();290291 let params = StartCollatorParams {292 para_id: id,293 block_status: client.clone(),294 announce_block,295 client: client.clone(),296 task_manager: &mut task_manager,297 collator_key,298 relay_chain_full_node,299 spawner,300 parachain_consensus,301 import_queue,302 };303304 start_collator(params).await?;305 } else {306 let params = StartFullNodeParams {307 client: client.clone(),308 announce_block,309 task_manager: &mut task_manager,310 para_id: id,311 relay_chain_full_node,312 };313314 start_full_node(params)?;315 }316317 start_network.start_network();318319 Ok((task_manager, client))320}321322323pub fn parachain_build_import_queue(324 client: Arc<TFullClient<Block, RuntimeApi, ParachainRuntimeExecutor>>,325 config: &Configuration,326 telemetry: Option<TelemetryHandle>,327 task_manager: &TaskManager,328) -> Result<329 sp_consensus::DefaultImportQueue<330 Block,331 TFullClient<Block, RuntimeApi, ParachainRuntimeExecutor>,332 >,333 sc_service::Error,334> {335 let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;336337338 cumulus_client_consensus_aura::import_queue::<339 sp_consensus_aura::sr25519::AuthorityPair,340 _,341 _,342 _,343 _,344 _,345 _,346 >(cumulus_client_consensus_aura::ImportQueueParams {347 block_import: client.clone(),348 client: client.clone(),349 create_inherent_data_providers: move |_, _| async move {350 let time = sp_timestamp::InherentDataProvider::from_system_time();351352 let slot =353 sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(354 *time,355 slot_duration.slot_duration(),356 );357358 Ok((time, slot))359 },360 registry: config.prometheus_registry().clone(),361 can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),362 spawner: &task_manager.spawn_essential_handle(),363 telemetry,364 })365 .map_err(Into::into)366}367368369pub async fn start_node(370 parachain_config: Configuration,371 collator_key: CollatorPair,372 polkadot_config: Configuration,373 id: ParaId,374) -> sc_service::error::Result<(TaskManager, Arc<TFullClient<Block, RuntimeApi, ParachainRuntimeExecutor>>)> {375 start_node_impl::<RuntimeApi, ParachainRuntimeExecutor, _, _, _>(376 parachain_config,377 collator_key,378 polkadot_config,379 id,380 |_| Default::default(),381 parachain_build_import_queue,382 |client,383 prometheus_registry,384 telemetry,385 task_manager,386 relay_chain_node,387 transaction_pool,388 sync_oracle,389 keystore,390 force_authoring| {391 let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;392393 let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(394 task_manager.spawn_handle(),395 client.clone(),396 transaction_pool,397 prometheus_registry.clone(),398 telemetry.clone(),399 );400401 let relay_chain_backend = relay_chain_node.backend.clone();402 let relay_chain_client = relay_chain_node.client.clone();403 Ok(build_aura_consensus::<404 sp_consensus_aura::sr25519::AuthorityPair,405 _,406 _,407 _,408 _,409 _,410 _,411 _,412 _,413 _,414 >(BuildAuraConsensusParams {415 proposer_factory,416 create_inherent_data_providers: move |_, (relay_parent, validation_data)| {417 let parachain_inherent =418 cumulus_primitives_parachain_inherent::ParachainInherentData::create_at_with_client(419 relay_parent,420 &relay_chain_client,421 &*relay_chain_backend,422 &validation_data,423 id,424 );425 async move {426 let time = sp_timestamp::InherentDataProvider::from_system_time();427428 let slot =429 sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(430 *time,431 slot_duration.slot_duration(),432 );433434 let parachain_inherent = parachain_inherent.ok_or_else(|| {435 Box::<dyn std::error::Error + Send + Sync>::from(436 "Failed to create parachain inherent",437 )438 })?;439 Ok((time, slot, parachain_inherent))440 }441 },442 block_import: client.clone(),443 relay_chain_client: relay_chain_node.client.clone(),444 relay_chain_backend: relay_chain_node.backend.clone(),445 para_client: client.clone(),446 backoff_authoring_blocks: Option::<()>::None,447 sync_oracle,448 keystore,449 force_authoring,450 slot_duration,451 452 block_proposal_slot_portion: SlotProportion::new(1f32 / 24f32),453 telemetry,454 }))455 },456 )457 .await458}