123456789101112131415161718use std::sync::Arc;19use std::sync::Mutex;20use std::collections::BTreeMap;21use std::time::Duration;22use std::pin::Pin;23use fc_mapping_sync::EthereumBlockNotificationSinks;24use fc_rpc::EthBlockDataCacheTask;25use fc_rpc::EthTask;26use fc_rpc_core::types::FeeHistoryCache;27use futures::{28 Stream, StreamExt,29 stream::select,30 task::{Context, Poll},31};32use sc_rpc::SubscriptionTaskExecutor;33use sp_keystore::KeystorePtr;34use tokio::time::Interval;35use jsonrpsee::RpcModule;3637use serde::{Serialize, Deserialize};383940use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, SlotProportion};41use cumulus_client_consensus_common::{42 ParachainConsensus, ParachainBlockImport as TParachainBlockImport,43};44use cumulus_client_service::{45 prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams,46};47use cumulus_client_cli::CollatorOptions;48use cumulus_client_network::BlockAnnounceValidator;49use cumulus_primitives_core::ParaId;50use cumulus_relay_chain_inprocess_interface::build_inprocess_relay_chain;51use cumulus_relay_chain_interface::{RelayChainInterface, RelayChainResult};52use cumulus_relay_chain_minimal_node::build_minimal_relay_chain_node;535455use sp_api::{BlockT, HeaderT, ProvideRuntimeApi, StateBackend};56use sc_executor::NativeElseWasmExecutor;57use sc_executor::NativeExecutionDispatch;58use sc_network::NetworkBlock;59use sc_network_sync::SyncingService;60use sc_service::{Configuration, PartialComponents, TaskManager};61use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle};62use sp_runtime::traits::BlakeTwo256;63use substrate_prometheus_endpoint::Registry;64use sc_client_api::{BlockchainEvents, BlockOf, Backend, AuxStore, StorageProvider};65use sp_blockchain::{HeaderBackend, HeaderMetadata, Error as BlockChainError};66use sc_consensus::ImportQueue;67use sp_core::H256;68use sp_block_builder::BlockBuilder;6970use polkadot_service::CollatorPair;717273use fc_rpc_core::types::FilterPool;74use fc_mapping_sync::{kv::MappingSyncWorker, SyncStrategy};75use fc_rpc::{76 StorageOverride, OverrideHandle, SchemaV1Override, SchemaV2Override, SchemaV3Override,77 RuntimeApiStorageOverride,78};79use fp_rpc::EthereumRuntimeRPCApi;80use fp_storage::EthereumStorageSchema;8182use up_common::types::opaque::*;8384use crate::chain_spec::RuntimeIdentification;858687#[cfg(feature = "unique-runtime")]88pub struct UniqueRuntimeExecutor;8990#[cfg(feature = "quartz-runtime")]9192pub struct QuartzRuntimeExecutor;939495pub struct OpalRuntimeExecutor;9697#[cfg(all(feature = "unique-runtime", feature = "runtime-benchmarks"))]98pub type DefaultRuntimeExecutor = UniqueRuntimeExecutor;99100#[cfg(all(101 not(feature = "unique-runtime"),102 feature = "quartz-runtime",103 feature = "runtime-benchmarks"104))]105pub type DefaultRuntimeExecutor = QuartzRuntimeExecutor;106107#[cfg(all(108 not(feature = "unique-runtime"),109 not(feature = "quartz-runtime"),110 feature = "runtime-benchmarks"111))]112pub type DefaultRuntimeExecutor = OpalRuntimeExecutor;113114#[cfg(feature = "unique-runtime")]115impl NativeExecutionDispatch for UniqueRuntimeExecutor {116 117 #[cfg(feature = "runtime-benchmarks")]118 type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;119 120 #[cfg(not(feature = "runtime-benchmarks"))]121 type ExtendHostFunctions = ();122123 fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {124 unique_runtime::api::dispatch(method, data)125 }126127 fn native_version() -> sc_executor::NativeVersion {128 unique_runtime::native_version()129 }130}131132#[cfg(feature = "quartz-runtime")]133impl NativeExecutionDispatch for QuartzRuntimeExecutor {134 135 #[cfg(feature = "runtime-benchmarks")]136 type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;137 138 #[cfg(not(feature = "runtime-benchmarks"))]139 type ExtendHostFunctions = ();140141 fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {142 quartz_runtime::api::dispatch(method, data)143 }144145 fn native_version() -> sc_executor::NativeVersion {146 quartz_runtime::native_version()147 }148}149150impl NativeExecutionDispatch for OpalRuntimeExecutor {151 152 #[cfg(feature = "runtime-benchmarks")]153 type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;154 155 #[cfg(not(feature = "runtime-benchmarks"))]156 type ExtendHostFunctions = ();157158 fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {159 opal_runtime::api::dispatch(method, data)160 }161162 fn native_version() -> sc_executor::NativeVersion {163 opal_runtime::native_version()164 }165}166167pub struct AutosealInterval {168 interval: Interval,169}170171impl AutosealInterval {172 pub fn new(config: &Configuration, interval: u64) -> Self {173 let _tokio_runtime = config.tokio_handle.enter();174 let interval = tokio::time::interval(Duration::from_millis(interval));175176 Self { interval }177 }178}179180impl Stream for AutosealInterval {181 type Item = tokio::time::Instant;182183 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {184 self.interval.poll_tick(cx).map(Some)185 }186}187188pub fn open_frontier_backend<C: HeaderBackend<Block>>(189 client: Arc<C>,190 config: &Configuration,191) -> Result<Arc<fc_db::kv::Backend<Block>>, String> {192 let config_dir = config.base_path.config_dir(config.chain_spec.id());193 let database_dir = config_dir.join("frontier").join("db");194195 Ok(Arc::new(fc_db::kv::Backend::<Block>::new(196 client,197 &fc_db::kv::DatabaseSettings {198 source: fc_db::DatabaseSource::RocksDb {199 path: database_dir,200 cache_size: 0,201 },202 },203 )?))204}205206type FullClient<RuntimeApi, ExecutorDispatch> =207 sc_service::TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ExecutorDispatch>>;208type FullBackend = sc_service::TFullBackend<Block>;209type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;210type ParachainBlockImport<RuntimeApi, ExecutorDispatch> =211 TParachainBlockImport<Block, Arc<FullClient<RuntimeApi, ExecutorDispatch>>, FullBackend>;212213214macro_rules! ez_bounds {215 ($vis:vis trait $name:ident$(<$($gen:ident $(: $($(+)? $bound:path)*)?),* $(,)?>)? $(:)? $($(+)? $super:path)* {}) => {216 $vis trait $name $(<$($gen $(: $($bound+)*)?,)*>)?: $($super +)* {}217 impl<T, $($($gen $(: $($bound+)*)?,)*)?> $name$(<$($gen,)*>)? for T218 where T: $($super +)* {}219 }220}221ez_bounds!(222 pub trait RuntimeApiDep<Runtime: RuntimeInstance>:223 sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>224 + sp_consensus_aura::AuraApi<Block, AuraId>225 + fp_rpc::EthereumRuntimeRPCApi<Block>226 + sp_session::SessionKeys<Block>227 + sp_block_builder::BlockBuilder<Block>228 + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>229 + sp_api::ApiExt<Block>230 + up_rpc::UniqueApi<Block, Runtime::CrossAccountId, AccountId>231 + app_promotion_rpc::AppPromotionApi<Block, BlockNumber, Runtime::CrossAccountId, AccountId>232 + up_pov_estimate_rpc::PovEstimateApi<Block>233 + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>234 + sp_api::Metadata<Block>235 + sp_offchain::OffchainWorkerApi<Block>236 + cumulus_primitives_core::CollectCollationInfo<Block>237 238 + fp_rpc::ConvertTransactionRuntimeApi<Block>239 {240 }241);242243244245246247#[allow(clippy::type_complexity)]248pub fn new_partial<Runtime, RuntimeApi, ExecutorDispatch, BIQ>(249 config: &Configuration,250 build_import_queue: BIQ,251) -> Result<252 PartialComponents<253 FullClient<RuntimeApi, ExecutorDispatch>,254 FullBackend,255 FullSelectChain,256 sc_consensus::DefaultImportQueue<Block>,257 sc_transaction_pool::FullPool<Block, FullClient<RuntimeApi, ExecutorDispatch>>,258 OtherPartial,259 >,260 sc_service::Error,261>262where263 sc_client_api::StateBackendFor<FullBackend, Block>: sp_api::StateBackend<BlakeTwo256>,264 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>265 + Send266 + Sync267 + 'static,268 RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,269 Runtime: RuntimeInstance,270 ExecutorDispatch: NativeExecutionDispatch + 'static,271 BIQ: FnOnce(272 Arc<FullClient<RuntimeApi, ExecutorDispatch>>,273 Arc<FullBackend>,274 &Configuration,275 Option<TelemetryHandle>,276 &TaskManager,277 ) -> Result<sc_consensus::DefaultImportQueue<Block>, sc_service::Error>,278{279 let telemetry = config280 .telemetry_endpoints281 .clone()282 .filter(|x| !x.is_empty())283 .map(|endpoints| -> Result<_, sc_telemetry::Error> {284 let worker = TelemetryWorker::new(16)?;285 let telemetry = worker.handle().new_telemetry(endpoints);286 Ok((worker, telemetry))287 })288 .transpose()?;289290 let executor = sc_service::new_native_or_wasm_executor(config);291292 let (client, backend, keystore_container, task_manager) =293 sc_service::new_full_parts::<Block, RuntimeApi, _>(294 config,295 telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),296 executor,297 )?;298 let client = Arc::new(client);299300 let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle());301302 let telemetry = telemetry.map(|(worker, telemetry)| {303 task_manager304 .spawn_handle()305 .spawn("telemetry", None, worker.run());306 telemetry307 });308309 let select_chain = sc_consensus::LongestChain::new(backend.clone());310311 let transaction_pool = sc_transaction_pool::BasicPool::new_full(312 config.transaction_pool.clone(),313 config.role.is_authority().into(),314 config.prometheus_registry(),315 task_manager.spawn_essential_handle(),316 client.clone(),317 );318319 let eth_filter_pool: Option<FilterPool> = Some(Arc::new(Mutex::new(BTreeMap::new())));320321 let eth_backend = open_frontier_backend(client.clone(), config)?;322323 let import_queue = build_import_queue(324 client.clone(),325 backend.clone(),326 config,327 telemetry.as_ref().map(|telemetry| telemetry.handle()),328 &task_manager,329 )?;330331 let params = PartialComponents {332 backend,333 client,334 import_queue,335 keystore_container,336 task_manager,337 transaction_pool,338 select_chain,339 other: OtherPartial {340 telemetry,341 eth_filter_pool,342 eth_backend,343 telemetry_worker_handle,344 },345 };346347 Ok(params)348}349350macro_rules! clone {351 ($($i:ident),* $(,)?) => {352 $(353 let $i = $i.clone();354 )*355 };356}357358359360361#[sc_tracing::logging::prefix_logs_with("Parachain")]362pub async fn start_node<Runtime, RuntimeApi, ExecutorDispatch>(363 parachain_config: Configuration,364 polkadot_config: Configuration,365 collator_options: CollatorOptions,366 para_id: ParaId,367 hwbench: Option<sc_sysinfo::HwBench>,368) -> sc_service::error::Result<(TaskManager, Arc<FullClient<RuntimeApi, ExecutorDispatch>>)>369where370 sc_client_api::StateBackendFor<FullBackend, Block>: sp_api::StateBackend<BlakeTwo256>,371 Runtime: RuntimeInstance + Send + Sync + 'static,372 <Runtime as RuntimeInstance>::CrossAccountId: Serialize,373 for<'de> <Runtime as RuntimeInstance>::CrossAccountId: Deserialize<'de>,374 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>375 + Send376 + Sync377 + 'static,378 RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,379 Runtime: RuntimeInstance,380 ExecutorDispatch: NativeExecutionDispatch + 'static,381{382 let parachain_config = prepare_node_config(parachain_config);383384 let params = new_partial::<Runtime, RuntimeApi, ExecutorDispatch, _>(385 ¶chain_config,386 parachain_build_import_queue,387 )?;388 let OtherPartial {389 mut telemetry,390 telemetry_worker_handle,391 eth_filter_pool,392 eth_backend,393 } = params.other;394 let net_config = sc_network::config::FullNetworkConfiguration::new(¶chain_config.network);395396 let client = params.client.clone();397 let backend = params.backend.clone();398 let mut task_manager = params.task_manager;399400 let (relay_chain_interface, collator_key) = build_relay_chain_interface(401 polkadot_config,402 ¶chain_config,403 telemetry_worker_handle,404 &mut task_manager,405 collator_options.clone(),406 hwbench.clone(),407 )408 .await409 .map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?;410411 let block_announce_validator =412 RequireSecondedInBlockAnnounce::new(relay_chain_interface.clone(), para_id);413414 let validator = parachain_config.role.is_authority();415 let prometheus_registry = parachain_config.prometheus_registry().cloned();416 let transaction_pool = params.transaction_pool.clone();417 let import_queue_service = params.import_queue.service();418419 let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) =420 sc_service::build_network(sc_service::BuildNetworkParams {421 config: ¶chain_config,422 net_config,423 client: client.clone(),424 transaction_pool: transaction_pool.clone(),425 spawn_handle: task_manager.spawn_handle(),426 import_queue: params.import_queue,427 block_announce_validator_builder: Some(Box::new(|_| {428 Box::new(block_announce_validator)429 })),430 warp_sync_params: None,431 })?;432433 let select_chain = params.select_chain.clone();434435 let runtime_id = parachain_config.chain_spec.runtime_id();436437 438 let fee_history_cache: FeeHistoryCache = Arc::new(Mutex::new(BTreeMap::new()));439 let fee_history_limit = 2048;440441 let eth_pubsub_notification_sinks: Arc<442 EthereumBlockNotificationSinks<fc_mapping_sync::EthereumBlockNotification<Block>>,443 > = Default::default();444445 let overrides = overrides_handle(client.clone());446 let eth_block_data_cache = spawn_frontier_tasks(447 FrontierTaskParams {448 client: client.clone(),449 substrate_backend: backend.clone(),450 eth_filter_pool: eth_filter_pool.clone(),451 eth_backend: eth_backend.clone(),452 fee_history_limit,453 fee_history_cache: fee_history_cache.clone(),454 task_manager: &task_manager,455 prometheus_registry: prometheus_registry.clone(),456 overrides: overrides.clone(),457 sync_strategy: SyncStrategy::Parachain,458 },459 sync_service.clone(),460 eth_pubsub_notification_sinks.clone(),461 );462463 464 let rpc_builder = Box::new({465 clone!(466 client,467 backend,468 eth_backend,469 eth_pubsub_notification_sinks,470 fee_history_cache,471 eth_block_data_cache,472 overrides,473 transaction_pool,474 network,475 sync_service,476 );477 move |deny_unsafe, subscription_task_executor: SubscriptionTaskExecutor| {478 clone!(479 backend,480 eth_block_data_cache,481 client,482 eth_backend,483 eth_filter_pool,484 eth_pubsub_notification_sinks,485 fee_history_cache,486 eth_block_data_cache,487 network,488 runtime_id,489 transaction_pool,490 select_chain,491 overrides,492 );493494 #[cfg(not(feature = "pov-estimate"))]495 let _ = backend;496497 let mut rpc_handle = RpcModule::new(());498499 let full_deps = FullDeps {500 client: client.clone(),501 runtime_id,502503 #[cfg(feature = "pov-estimate")]504 exec_params: uc_rpc::pov_estimate::ExecutorParams {505 wasm_method: parachain_config.wasm_method,506 default_heap_pages: parachain_config.default_heap_pages,507 max_runtime_instances: parachain_config.max_runtime_instances,508 runtime_cache_size: parachain_config.runtime_cache_size,509 },510511 #[cfg(feature = "pov-estimate")]512 backend,513514 deny_unsafe,515 pool: transaction_pool.clone(),516 select_chain,517 };518519 create_full::<_, _, _, Runtime, RuntimeApi, _>(&mut rpc_handle, full_deps)?;520521 let eth_deps = EthDeps {522 client,523 graph: transaction_pool.pool().clone(),524 pool: transaction_pool,525 is_authority: validator,526 network,527 eth_backend,528 529 max_past_logs: 10000,530 fee_history_limit,531 fee_history_cache,532 eth_block_data_cache,533 534 enable_dev_signer: false,535 eth_filter_pool,536 eth_pubsub_notification_sinks,537 overrides,538 sync: sync_service.clone(),539 pending_create_inherent_data_providers: |_, ()| async move { Ok(()) },540 };541542 create_eth::<543 _,544 _,545 _,546 _,547 _,548 _,549 DefaultEthConfig<FullClient<RuntimeApi, ExecutorDispatch>>,550 >(551 &mut rpc_handle,552 eth_deps,553 subscription_task_executor.clone(),554 )?;555556 Ok(rpc_handle)557 }558 });559560 sc_service::spawn_tasks(sc_service::SpawnTasksParams {561 rpc_builder,562 client: client.clone(),563 transaction_pool: transaction_pool.clone(),564 task_manager: &mut task_manager,565 config: parachain_config,566 keystore: params.keystore_container.keystore(),567 backend: backend.clone(),568 network: network.clone(),569 sync_service: sync_service.clone(),570 system_rpc_tx,571 telemetry: telemetry.as_mut(),572 tx_handler_controller,573 })?;574575 if let Some(hwbench) = hwbench {576 sc_sysinfo::print_hwbench(&hwbench);577578 if let Some(ref mut telemetry) = telemetry {579 let telemetry_handle = telemetry.handle();580 task_manager.spawn_handle().spawn(581 "telemetry_hwbench",582 None,583 sc_sysinfo::initialize_hwbench_telemetry(telemetry_handle, hwbench),584 );585 }586 }587588 let announce_block = {589 let sync_service = sync_service.clone();590 Arc::new(Box::new(move |hash, data| {591 sync_service.announce_block(hash, data)592 }))593 };594595 let relay_chain_slot_duration = Duration::from_secs(6);596597 let overseer_handle = relay_chain_interface598 .overseer_handle()599 .map_err(|e| sc_service::Error::Application(Box::new(e)))?;600601 start_relay_chain_tasks(StartRelayChainTasksParams {602 client: client.clone(),603 announce_block: announce_block.clone(),604 para_id,605 relay_chain_interface: relay_chain_interface.clone(),606 task_manager: &mut task_manager,607 da_recovery_profile: if validator {608 DARecoveryProfile::Collator609 } else {610 DARecoveryProfile::FullNode611 },612 import_queue: import_queue_service,613 relay_chain_slot_duration,614 recovery_handle: Box::new(overseer_handle.clone()),615 sync_service: sync_service.clone(),616 })?;617618 if validator {619 start_consensus(620 client.clone(),621 backend.clone(),622 prometheus_registry.as_ref(),623 telemetry.as_ref().map(|t| t.handle()),624 &task_manager,625 relay_chain_interface.clone(),626 transaction_pool,627 sync_service.clone(),628 params.keystore_container.keystore(),629 overseer_handle,630 relay_chain_slot_duration,631 para_id,632 collator_key.expect("cli args do not allow this"),633 announce_block,634 )?;635 }636637 start_network.start_network();638639 Ok((task_manager, client))640}641642643pub fn parachain_build_import_queue<Runtime, RuntimeApi, ExecutorDispatch>(644 client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,645 backend: Arc<FullBackend>,646 config: &Configuration,647 telemetry: Option<TelemetryHandle>,648 task_manager: &TaskManager,649) -> Result<sc_consensus::DefaultImportQueue<Block>, sc_service::Error>650where651 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>652 + Send653 + Sync654 + 'static,655 RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,656 Runtime: RuntimeInstance,657 ExecutorDispatch: NativeExecutionDispatch + 'static,658{659 let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;660661 let block_import = ParachainBlockImport::new(client.clone(), backend);662663 cumulus_client_consensus_aura::import_queue::<664 sp_consensus_aura::sr25519::AuthorityPair,665 _,666 _,667 _,668 _,669 _,670 >(cumulus_client_consensus_aura::ImportQueueParams {671 block_import,672 client,673 create_inherent_data_providers: move |_, _| async move {674 let time = sp_timestamp::InherentDataProvider::from_system_time();675676 let slot =677 sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(678 *time,679 slot_duration,680 );681682 Ok((slot, time))683 },684 registry: config.prometheus_registry(),685 spawner: &task_manager.spawn_essential_handle(),686 telemetry,687 })688 .map_err(Into::into)689}690691pub fn start_consensus<ExecutorDispatch, RuntimeApi, Runtime>(692 client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,693 backend: Arc<FullBackend>,694 prometheus_registry: Option<&Registry>,695 telemetry: Option<TelemetryHandle>,696 task_manager: &TaskManager,697 relay_chain_interface: Arc<dyn RelayChainInterface>,698 transaction_pool: Arc<699 sc_transaction_pool::FullPool<Block, FullClient<RuntimeApi, ExecutorDispatch>>,700 >,701 sync_oracle: Arc<SyncingService<Block>>,702 keystore: KeystorePtr,703 overseer_handle: OverseerHandle,704 relay_chain_slot_duration: Duration,705 para_id: ParaId,706 collator_key: CollatorPair,707 announce_block: Arc<dyn Fn(Hash, Option<Vec<u8>>) + Send + Sync>,708) -> Result<(), sc_service::Error>709where710 ExecutorDispatch: NativeExecutionDispatch + 'static,711 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>712 + Send713 + Sync714 + 'static,715 RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,716 Runtime: RuntimeInstance,717{718 let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;719720 let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(721 task_manager.spawn_handle(),722 client.clone(),723 transaction_pool,724 prometheus_registry,725 telemetry.clone(),726 );727 let proposer = Proposer::new(proposer_factory);728729 let collator_service = CollatorService::new(730 client.clone(),731 Arc::new(task_manager.spawn_handle()),732 announce_block,733 client.clone(),734 );735736 let block_import = ParachainBlockImport::new(client.clone(), backend);737738 let params = BuildAuraConsensusParams {739 create_inherent_data_providers: move |_, ()| async move { Ok(()) },740 block_import,741 para_client: client,742 #[cfg(feature = "lookahead")]743 para_backend: backend,744 para_id,745 relay_client: relay_chain_interface,746 sync_oracle,747 keystore,748 slot_duration,749 proposer,750 collator_service,751 752 authoring_duration: Duration::from_millis(500),753 overseer_handle,754 #[cfg(feature = "lookahead")]755 code_hash_provider: || {},756 collator_key,757 relay_chain_slot_duration,758 };759760 task_manager.spawn_essential_handle().spawn(761 "aura",762 None,763 run_aura::<_, AuraAuthorityPair, _, _, _, _, _, _, _>(params),764 );765 Ok(())766}767768fn dev_build_import_queue<RuntimeApi, ExecutorDispatch>(769 client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,770 _: Arc<FullBackend>,771 config: &Configuration,772 _: Option<TelemetryHandle>,773 task_manager: &TaskManager,774) -> Result<sc_consensus::DefaultImportQueue<Block>, sc_service::Error>775where776 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>777 + Send778 + Sync779 + 'static,780 RuntimeApi::RuntimeApi:781 sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> + sp_api::ApiExt<Block>,782 ExecutorDispatch: NativeExecutionDispatch + 'static,783{784 Ok(sc_consensus_manual_seal::import_queue(785 Box::new(client),786 &task_manager.spawn_essential_handle(),787 config.prometheus_registry(),788 ))789}790791pub struct OtherPartial {792 pub telemetry: Option<Telemetry>,793 pub telemetry_worker_handle: Option<TelemetryWorkerHandle>,794 pub eth_filter_pool: Option<FilterPool>,795 pub eth_backend: Arc<fc_db::kv::Backend<Block>>,796}797798struct DefaultEthConfig<C>(PhantomData<C>);799impl<C> EthConfig<Block, C> for DefaultEthConfig<C>800where801 C: StorageProvider<Block, FullBackend> + Sync + Send + 'static,802{803 type EstimateGasAdapter = ();804 type RuntimeStorageOverride = SystemAccountId32StorageOverride<Block, C, FullBackend>;805}806807808809pub fn start_dev_node<Runtime, RuntimeApi, ExecutorDispatch>(810 config: Configuration,811 autoseal_interval: u64,812 autoseal_finalize_delay: Option<u64>,813 disable_autoseal_on_tx: bool,814) -> sc_service::error::Result<TaskManager>815where816 Runtime: RuntimeInstance + Send + Sync + 'static,817 <Runtime as RuntimeInstance>::CrossAccountId: Serialize,818 for<'de> <Runtime as RuntimeInstance>::CrossAccountId: Deserialize<'de>,819 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>820 + Send821 + Sync822 + 'static,823 RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,824 ExecutorDispatch: NativeExecutionDispatch + 'static,825{826 use fc_consensus::FrontierBlockImport;827 use sc_consensus_manual_seal::{828 run_manual_seal, run_delayed_finalize, EngineCommand, ManualSealParams,829 DelayedFinalizeParams,830 };831832 let sc_service::PartialComponents {833 client,834 backend,835 mut task_manager,836 import_queue,837 keystore_container,838 select_chain: maybe_select_chain,839 transaction_pool,840 other:841 OtherPartial {842 telemetry,843 eth_filter_pool,844 eth_backend,845 telemetry_worker_handle: _,846 },847 } = new_partial::<Runtime, RuntimeApi, ExecutorDispatch, _>(848 &config,849 dev_build_import_queue::<RuntimeApi, ExecutorDispatch>,850 )?;851 let net_config = sc_network::config::FullNetworkConfiguration::new(&config.network);852 let prometheus_registry = config.prometheus_registry().cloned();853854 let (network, system_rpc_tx, tx_handler_controller, network_starter, sync_service) =855 sc_service::build_network(sc_service::BuildNetworkParams {856 config: &config,857 net_config,858 client: client.clone(),859 transaction_pool: transaction_pool.clone(),860 spawn_handle: task_manager.spawn_handle(),861 import_queue,862 block_announce_validator_builder: None,863 warp_sync_params: None,864 })?;865866 let collator = config.role.is_authority();867868 let select_chain = maybe_select_chain;869870 if collator {871 let block_import = FrontierBlockImport::new(client.clone(), client.clone());872873 let env = sc_basic_authorship::ProposerFactory::new(874 task_manager.spawn_handle(),875 client.clone(),876 transaction_pool.clone(),877 prometheus_registry.as_ref(),878 telemetry.as_ref().map(|x| x.handle()),879 );880881 let transactions_commands_stream: Box<882 dyn Stream<Item = EngineCommand<Hash>> + Send + Sync + Unpin,883 > = Box::new(884 transaction_pool885 .pool()886 .validated_pool()887 .import_notification_stream()888 .filter(move |_| futures::future::ready(!disable_autoseal_on_tx))889 .map(|_| EngineCommand::SealNewBlock {890 create_empty: true,891 finalize: false,892 parent_hash: None,893 sender: None,894 }),895 );896897 let autoseal_interval = Box::pin(AutosealInterval::new(&config, autoseal_interval));898899 let idle_commands_stream: Box<900 dyn Stream<Item = EngineCommand<Hash>> + Send + Sync + Unpin,901 > = Box::new(autoseal_interval.map(|_| EngineCommand::SealNewBlock {902 create_empty: true,903 finalize: false,904 parent_hash: None,905 sender: None,906 }));907908 let commands_stream = select(transactions_commands_stream, idle_commands_stream);909910 let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;911 let client_set_aside_for_cidp = client.clone();912913 if let Some(delay_sec) = autoseal_finalize_delay {914 let spawn_handle = task_manager.spawn_handle();915916 task_manager.spawn_essential_handle().spawn_blocking(917 "finalization_task",918 Some("block-authoring"),919 run_delayed_finalize(DelayedFinalizeParams {920 client: client.clone(),921 delay_sec,922 spawn_handle,923 }),924 );925 }926927 task_manager.spawn_essential_handle().spawn_blocking(928 "authorship_task",929 Some("block-authoring"),930 run_manual_seal(ManualSealParams {931 block_import,932 env,933 client: client.clone(),934 pool: transaction_pool.clone(),935 commands_stream,936 select_chain: select_chain.clone(),937 consensus_data_provider: None,938 create_inherent_data_providers: move |block: Hash, ()| {939 let current_para_block = client_set_aside_for_cidp940 .number(block)941 .expect("Header lookup should succeed")942 .expect("Header passed in as parent should be present in backend.");943944 let client_for_xcm = client_set_aside_for_cidp.clone();945 async move {946 let time = sp_timestamp::InherentDataProvider::from_system_time();947948 let mocked_parachain = cumulus_primitives_parachain_inherent::MockValidationDataInherentDataProvider {949 current_para_block,950 relay_offset: 1000,951 relay_blocks_per_para_block: 2,952 para_blocks_per_relay_epoch: 0,953 xcm_config: cumulus_primitives_parachain_inherent::MockXcmConfig::new(954 &*client_for_xcm,955 block,956 Default::default(),957 Default::default(),958 ),959 relay_randomness_config: (),960 raw_downward_messages: vec![],961 raw_horizontal_messages: vec![],962 };963964 let slot =965 sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(966 *time,967 slot_duration,968 );969970 Ok((time, slot, mocked_parachain))971 }972 },973 }),974 );975 }976977 #[cfg(feature = "pov-estimate")]978 let rpc_backend = backend.clone();979980 let runtime_id = config.chain_spec.runtime_id();981982 983 let fee_history_cache: FeeHistoryCache = Arc::new(Mutex::new(BTreeMap::new()));984 let fee_history_limit = 2048;985986 let eth_pubsub_notification_sinks: Arc<987 EthereumBlockNotificationSinks<fc_mapping_sync::EthereumBlockNotification<Block>>,988 > = Default::default();989990 let overrides = overrides_handle(client.clone());991 let eth_block_data_cache = spawn_frontier_tasks(992 FrontierTaskParams {993 client: client.clone(),994 substrate_backend: backend.clone(),995 eth_filter_pool: eth_filter_pool.clone(),996 eth_backend: eth_backend.clone(),997 fee_history_limit,998 fee_history_cache: fee_history_cache.clone(),999 task_manager: &task_manager,1000 prometheus_registry,1001 overrides: overrides.clone(),1002 sync_strategy: SyncStrategy::Normal,1003 },1004 sync_service.clone(),1005 eth_pubsub_notification_sinks.clone(),1006 );10071008 1009 let rpc_builder = Box::new({1010 clone!(1011 client,1012 backend,1013 eth_backend,1014 eth_pubsub_notification_sinks,1015 fee_history_cache,1016 eth_block_data_cache,1017 overrides,1018 transaction_pool,1019 network,1020 sync_service,1021 );1022 move |deny_unsafe, subscription_task_executor: SubscriptionTaskExecutor| {1023 clone!(1024 backend,1025 eth_block_data_cache,1026 client,1027 eth_backend,1028 eth_filter_pool,1029 eth_pubsub_notification_sinks,1030 fee_history_cache,1031 eth_block_data_cache,1032 network,1033 runtime_id,1034 transaction_pool,1035 select_chain,1036 overrides,1037 );10381039 #[cfg(not(feature = "pov-estimate"))]1040 let _ = backend;10411042 let mut rpc_module = RpcModule::new(());10431044 let full_deps = FullDeps {1045 runtime_id,10461047 #[cfg(feature = "pov-estimate")]1048 exec_params: uc_rpc::pov_estimate::ExecutorParams {1049 wasm_method: config.wasm_method,1050 default_heap_pages: config.default_heap_pages,1051 max_runtime_instances: config.max_runtime_instances,1052 runtime_cache_size: config.runtime_cache_size,1053 },10541055 #[cfg(feature = "pov-estimate")]1056 backend,1057 1058 deny_unsafe,1059 client: client.clone(),1060 pool: transaction_pool.clone(),1061 select_chain,1062 };10631064 create_full::<_, _, _, Runtime, RuntimeApi, _>(&mut rpc_module, full_deps)?;10651066 let eth_deps = EthDeps {1067 client,1068 graph: transaction_pool.pool().clone(),1069 pool: transaction_pool,1070 is_authority: true,1071 network,1072 eth_backend,1073 1074 max_past_logs: 10000,1075 fee_history_limit,1076 fee_history_cache,1077 eth_block_data_cache,1078 1079 enable_dev_signer: false,1080 eth_filter_pool,1081 eth_pubsub_notification_sinks,1082 overrides,1083 sync: sync_service.clone(),1084 1085 pending_create_inherent_data_providers: |_, ()| async move { Ok(()) },1086 };10871088 create_eth::<1089 _,1090 _,1091 _,1092 _,1093 _,1094 _,1095 DefaultEthConfig<FullClient<RuntimeApi, ExecutorDispatch>>,1096 >(1097 &mut rpc_module,1098 eth_deps,1099 subscription_task_executor.clone(),1100 )?;11011102 Ok(rpc_module)1103 }1104 });11051106 sc_service::spawn_tasks(sc_service::SpawnTasksParams {1107 network,1108 sync_service,1109 client,1110 keystore: keystore_container.keystore(),1111 task_manager: &mut task_manager,1112 transaction_pool,1113 rpc_builder,1114 backend,1115 system_rpc_tx,1116 config,1117 telemetry: None,1118 tx_handler_controller,1119 })?;11201121 network_starter.start_network();1122 Ok(task_manager)1123}11241125fn overrides_handle<C, BE>(client: Arc<C>) -> Arc<OverrideHandle<Block>>1126where1127 C: ProvideRuntimeApi<Block> + StorageProvider<Block, BE> + AuxStore,1128 C: HeaderBackend<Block> + HeaderMetadata<Block, Error = BlockChainError>,1129 C: Send + Sync + 'static,1130 C::Api: fp_rpc::EthereumRuntimeRPCApi<Block>,1131 BE: Backend<Block> + 'static,1132 BE::State: StateBackend<BlakeTwo256>,1133{1134 let mut overrides_map = BTreeMap::new();1135 overrides_map.insert(1136 EthereumStorageSchema::V1,1137 Box::new(SchemaV1Override::new(client.clone())) as Box<dyn StorageOverride<_> + 'static>,1138 );1139 overrides_map.insert(1140 EthereumStorageSchema::V2,1141 Box::new(SchemaV2Override::new(client.clone())) as Box<dyn StorageOverride<_> + 'static>,1142 );1143 overrides_map.insert(1144 EthereumStorageSchema::V3,1145 Box::new(SchemaV3Override::new(client.clone())) as Box<dyn StorageOverride<_> + 'static>,1146 );11471148 Arc::new(OverrideHandle {1149 schemas: overrides_map,1150 fallback: Box::new(RuntimeApiStorageOverride::new(client)),1151 })1152}11531154pub struct FrontierTaskParams<'a, C, B> {1155 pub task_manager: &'a TaskManager,1156 pub client: Arc<C>,1157 pub substrate_backend: Arc<B>,1158 pub eth_backend: Arc<fc_db::kv::Backend<Block>>,1159 pub eth_filter_pool: Option<FilterPool>,1160 pub overrides: Arc<OverrideHandle<Block>>,1161 pub fee_history_limit: u64,1162 pub fee_history_cache: FeeHistoryCache,1163 pub sync_strategy: SyncStrategy,1164 pub prometheus_registry: Option<Registry>,1165}11661167pub fn spawn_frontier_tasks<C, B>(1168 params: FrontierTaskParams<C, B>,1169 sync: Arc<SyncingService<Block>>,1170 pubsub_notification_sinks: Arc<1171 EthereumBlockNotificationSinks<fc_mapping_sync::EthereumBlockNotification<Block>>,1172 >,1173) -> Arc<EthBlockDataCacheTask<Block>>1174where1175 C: ProvideRuntimeApi<Block> + BlockOf,1176 C: HeaderBackend<Block> + HeaderMetadata<Block, Error = BlockChainError> + 'static,1177 C: BlockchainEvents<Block> + StorageProvider<Block, B>,1178 C: Send + Sync + 'static,1179 C::Api: EthereumRuntimeRPCApi<Block>,1180 C::Api: BlockBuilder<Block>,1181 B: Backend<Block> + 'static,1182 B::State: StateBackend<BlakeTwo256>,1183{1184 let FrontierTaskParams {1185 task_manager,1186 client,1187 substrate_backend,1188 eth_backend,1189 eth_filter_pool,1190 overrides,1191 fee_history_limit,1192 fee_history_cache,1193 sync_strategy,1194 prometheus_registry,1195 } = params;1196 1197 1198 params.task_manager.spawn_essential_handle().spawn(1199 "frontier-mapping-sync-worker",1200 Some("frontier"),1201 MappingSyncWorker::new(1202 client.import_notification_stream(),1203 Duration::new(6, 0),1204 client.clone(),1205 substrate_backend,1206 overrides.clone(),1207 eth_backend,1208 3,1209 0,1210 sync_strategy,1211 sync,1212 pubsub_notification_sinks,1213 )1214 .for_each(|()| futures::future::ready(())),1215 );12161217 1218 1219 if let Some(eth_filter_pool) = eth_filter_pool {1220 1221 const FILTER_RETAIN_THRESHOLD: u64 = 100;1222 params.task_manager.spawn_essential_handle().spawn(1223 "frontier-filter-pool",1224 Some("frontier"),1225 EthTask::filter_pool_task(client.clone(), eth_filter_pool, FILTER_RETAIN_THRESHOLD),1226 );1227 }12281229 1230 params.task_manager.spawn_essential_handle().spawn(1231 "frontier-fee-history",1232 Some("frontier"),1233 EthTask::fee_history_task(1234 client,1235 overrides.clone(),1236 fee_history_cache,1237 fee_history_limit,1238 ),1239 );12401241 Arc::new(EthBlockDataCacheTask::new(1242 task_manager.spawn_handle(),1243 overrides,1244 50,1245 50,1246 prometheus_registry,1247 ))1248}