123456789101112131415161718use std::{19 collections::BTreeMap,20 marker::PhantomData,21 pin::Pin,22 sync::{Arc, Mutex},23 time::Duration,24};2526use cumulus_client_cli::CollatorOptions;27use cumulus_client_collator::service::CollatorService;28#[cfg(not(feature = "lookahead"))]29use cumulus_client_consensus_aura::collators::basic::{30 run as run_aura, Params as BuildAuraConsensusParams,31};32#[cfg(feature = "lookahead")]33use cumulus_client_consensus_aura::collators::lookahead::{34 run as run_aura, Params as BuildAuraConsensusParams,35};36use cumulus_client_consensus_common::ParachainBlockImport as TParachainBlockImport;37use cumulus_client_consensus_proposer::Proposer;38use cumulus_client_service::{39 build_relay_chain_interface, prepare_node_config, start_relay_chain_tasks,40 CollatorSybilResistance, DARecoveryProfile, StartRelayChainTasksParams,41};42use cumulus_primitives_core::ParaId;43use cumulus_primitives_parachain_inherent::ParachainInherentData;44use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface};45use fc_mapping_sync::{kv::MappingSyncWorker, EthereumBlockNotificationSinks, SyncStrategy};46use fc_rpc::{47 frontier_backend_client::SystemAccountId32StorageOverride, EthBlockDataCacheTask, EthConfig,48 EthTask, OverrideHandle, RuntimeApiStorageOverride, SchemaV1Override, SchemaV2Override,49 SchemaV3Override, StorageOverride,50};51use fc_rpc_core::types::{FeeHistoryCache, FilterPool};52use fp_rpc::EthereumRuntimeRPCApi;53use fp_storage::EthereumStorageSchema;54use futures::{55 stream::select,56 task::{Context, Poll},57 Stream, StreamExt,58};59use jsonrpsee::RpcModule;60use polkadot_service::CollatorPair;61use sc_client_api::{AuxStore, Backend, BlockOf, BlockchainEvents, StorageProvider};62use sc_consensus::ImportQueue;63use sc_executor::{NativeElseWasmExecutor, NativeExecutionDispatch};64use sc_network::NetworkBlock;65use sc_network_sync::SyncingService;66use sc_rpc::SubscriptionTaskExecutor;67use sc_service::{Configuration, PartialComponents, TaskManager};68use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle};69use serde::{Deserialize, Serialize};70use sp_api::ProvideRuntimeApi;71use sp_block_builder::BlockBuilder;72use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};73use sp_consensus_aura::sr25519::AuthorityPair as AuraAuthorityPair;74use sp_keystore::KeystorePtr;75use sp_state_machine::Backend as StateBackend;76use substrate_prometheus_endpoint::Registry;77use tokio::time::Interval;78use up_common::types::{opaque::*, Nonce};7980pub type ParachainHostFunctions = (81 sp_io::SubstrateHostFunctions,82 cumulus_client_service::storage_proof_size::HostFunctions,83);8485use cumulus_primitives_core::PersistedValidationData;86use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder;8788use crate::rpc::{create_eth, create_full, EthDeps, FullDeps};899091#[cfg(feature = "unique-runtime")]92pub struct UniqueRuntimeExecutor;9394#[cfg(feature = "quartz-runtime")]9596pub struct QuartzRuntimeExecutor;979899pub struct OpalRuntimeExecutor;100101#[cfg(feature = "unique-runtime")]102impl NativeExecutionDispatch for UniqueRuntimeExecutor {103 104 #[cfg(feature = "runtime-benchmarks")]105 type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;106 107 #[cfg(not(feature = "runtime-benchmarks"))]108 type ExtendHostFunctions = ParachainHostFunctions;109110 fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {111 unique_runtime::api::dispatch(method, data)112 }113114 fn native_version() -> sc_executor::NativeVersion {115 unique_runtime::native_version()116 }117}118119#[cfg(feature = "quartz-runtime")]120impl NativeExecutionDispatch for QuartzRuntimeExecutor {121 122 #[cfg(feature = "runtime-benchmarks")]123 type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;124 125 #[cfg(not(feature = "runtime-benchmarks"))]126 type ExtendHostFunctions = ParachainHostFunctions;127128 fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {129 quartz_runtime::api::dispatch(method, data)130 }131132 fn native_version() -> sc_executor::NativeVersion {133 quartz_runtime::native_version()134 }135}136137impl NativeExecutionDispatch for OpalRuntimeExecutor {138 139 #[cfg(feature = "runtime-benchmarks")]140 type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;141 142 #[cfg(not(feature = "runtime-benchmarks"))]143 type ExtendHostFunctions = ParachainHostFunctions;144145 fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {146 opal_runtime::api::dispatch(method, data)147 }148149 fn native_version() -> sc_executor::NativeVersion {150 opal_runtime::native_version()151 }152}153154pub struct AutosealInterval {155 interval: Interval,156}157158impl AutosealInterval {159 pub fn new(config: &Configuration, interval: u64) -> Self {160 let _tokio_runtime = config.tokio_handle.enter();161 let interval = tokio::time::interval(Duration::from_millis(interval));162163 Self { interval }164 }165}166167impl Stream for AutosealInterval {168 type Item = tokio::time::Instant;169170 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {171 self.interval.poll_tick(cx).map(Some)172 }173}174175pub fn open_frontier_backend<C: HeaderBackend<Block>>(176 client: Arc<C>,177 config: &Configuration,178) -> Result<Arc<fc_db::kv::Backend<Block>>, String> {179 let config_dir = config.base_path.config_dir(config.chain_spec.id());180 let database_dir = config_dir.join("frontier").join("db");181182 Ok(Arc::new(fc_db::kv::Backend::<Block>::new(183 client,184 &fc_db::kv::DatabaseSettings {185 source: fc_db::DatabaseSource::RocksDb {186 path: database_dir,187 cache_size: 0,188 },189 },190 )?))191}192193type FullClient<RuntimeApi, ExecutorDispatch> =194 sc_service::TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ExecutorDispatch>>;195type FullBackend = sc_service::TFullBackend<Block>;196type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;197type ParachainBlockImport<RuntimeApi, ExecutorDispatch> =198 TParachainBlockImport<Block, Arc<FullClient<RuntimeApi, ExecutorDispatch>>, FullBackend>;199200201macro_rules! ez_bounds {202 ($vis:vis trait $name:ident$(<$($gen:ident $(: $($(+)? $bound:path)*)?),* $(,)?>)? $(:)? $($(+)? $super:path)* {}) => {203 $vis trait $name $(<$($gen $(: $($bound+)*)?,)*>)?: $($super +)* {}204 impl<T, $($($gen $(: $($bound+)*)?,)*)?> $name$(<$($gen,)*>)? for T205 where T: $($super +)* {}206 }207}208ez_bounds!(209 pub trait RuntimeApiDep<Runtime: RuntimeInstance>:210 sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>211 + sp_consensus_aura::AuraApi<Block, AuraId>212 + fp_rpc::EthereumRuntimeRPCApi<Block>213 + sp_session::SessionKeys<Block>214 + sp_block_builder::BlockBuilder<Block>215 + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>216 + sp_api::ApiExt<Block>217 + up_rpc::UniqueApi<Block, Runtime::CrossAccountId, AccountId>218 + app_promotion_rpc::AppPromotionApi<Block, BlockNumber, Runtime::CrossAccountId, AccountId>219 + up_pov_estimate_rpc::PovEstimateApi<Block>220 + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>221 + sp_api::Metadata<Block>222 + sp_offchain::OffchainWorkerApi<Block>223 + cumulus_primitives_core::CollectCollationInfo<Block>224 225 + fp_rpc::ConvertTransactionRuntimeApi<Block>226 {227 }228);229#[cfg(not(feature = "lookahead"))]230ez_bounds!(231 pub trait LookaheadApiDep {}232);233#[cfg(feature = "lookahead")]234ez_bounds!(235 pub trait LookaheadApiDep: cumulus_primitives_aura::AuraUnincludedSegmentApi<Block> {}236);237238fn ethereum_parachain_inherent() -> (sp_timestamp::InherentDataProvider, ParachainInherentData) {239 let (relay_parent_storage_root, relay_chain_state) =240 RelayStateSproofBuilder::default().into_state_root_and_proof();241 let vfp = PersistedValidationData {242 243 244 relay_parent_number: u32::MAX,245 relay_parent_storage_root,246 ..Default::default()247 };248249 (250 sp_timestamp::InherentDataProvider::from_system_time(),251 ParachainInherentData {252 validation_data: vfp,253 relay_chain_state,254 downward_messages: Default::default(),255 horizontal_messages: Default::default(),256 },257 )258}259260261262263264#[allow(clippy::type_complexity)]265pub fn new_partial<Runtime, RuntimeApi, ExecutorDispatch, BIQ>(266 config: &Configuration,267 build_import_queue: BIQ,268) -> Result<269 PartialComponents<270 FullClient<RuntimeApi, ExecutorDispatch>,271 FullBackend,272 FullSelectChain,273 sc_consensus::DefaultImportQueue<Block>,274 sc_transaction_pool::FullPool<Block, FullClient<RuntimeApi, ExecutorDispatch>>,275 OtherPartial,276 >,277 sc_service::Error,278>279where280 sc_client_api::StateBackendFor<FullBackend, Block>: StateBackend<BlakeTwo256>,281 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>282 + Send283 + Sync284 + 'static,285 RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,286 Runtime: RuntimeInstance,287 ExecutorDispatch: NativeExecutionDispatch + 'static,288 BIQ: FnOnce(289 Arc<FullClient<RuntimeApi, ExecutorDispatch>>,290 Arc<FullBackend>,291 &Configuration,292 Option<TelemetryHandle>,293 &TaskManager,294 ) -> Result<sc_consensus::DefaultImportQueue<Block>, sc_service::Error>,295{296 let telemetry = config297 .telemetry_endpoints298 .clone()299 .filter(|x| !x.is_empty())300 .map(|endpoints| -> Result<_, sc_telemetry::Error> {301 let worker = TelemetryWorker::new(16)?;302 let telemetry = worker.handle().new_telemetry(endpoints);303 Ok((worker, telemetry))304 })305 .transpose()?;306307 let executor = sc_service::new_native_or_wasm_executor(config);308309 let (client, backend, keystore_container, task_manager) =310 sc_service::new_full_parts::<Block, RuntimeApi, _>(311 config,312 telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),313 executor,314 )?;315 let client = Arc::new(client);316317 let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle());318319 let telemetry = telemetry.map(|(worker, telemetry)| {320 task_manager321 .spawn_handle()322 .spawn("telemetry", None, worker.run());323 telemetry324 });325326 let select_chain = sc_consensus::LongestChain::new(backend.clone());327328 let transaction_pool = sc_transaction_pool::BasicPool::new_full(329 config.transaction_pool.clone(),330 config.role.is_authority().into(),331 config.prometheus_registry(),332 task_manager.spawn_essential_handle(),333 client.clone(),334 );335336 let eth_filter_pool: Option<FilterPool> = Some(Arc::new(Mutex::new(BTreeMap::new())));337338 let eth_backend = open_frontier_backend(client.clone(), config)?;339340 let import_queue = build_import_queue(341 client.clone(),342 backend.clone(),343 config,344 telemetry.as_ref().map(|telemetry| telemetry.handle()),345 &task_manager,346 )?;347348 let params = PartialComponents {349 backend,350 client,351 import_queue,352 keystore_container,353 task_manager,354 transaction_pool,355 select_chain,356 other: OtherPartial {357 telemetry,358 eth_filter_pool,359 eth_backend,360 telemetry_worker_handle,361 },362 };363364 Ok(params)365}366367macro_rules! clone {368 ($($i:ident),* $(,)?) => {369 $(370 let $i = $i.clone();371 )*372 };373}374375376377378#[sc_tracing::logging::prefix_logs_with("Parachain")]379pub async fn start_node<Runtime, RuntimeApi, ExecutorDispatch>(380 parachain_config: Configuration,381 polkadot_config: Configuration,382 collator_options: CollatorOptions,383 para_id: ParaId,384 hwbench: Option<sc_sysinfo::HwBench>,385) -> sc_service::error::Result<(TaskManager, Arc<FullClient<RuntimeApi, ExecutorDispatch>>)>386where387 sc_client_api::StateBackendFor<FullBackend, Block>: StateBackend<BlakeTwo256>,388 Runtime: RuntimeInstance + Send + Sync + 'static,389 <Runtime as RuntimeInstance>::CrossAccountId: Serialize,390 for<'de> <Runtime as RuntimeInstance>::CrossAccountId: Deserialize<'de>,391 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>392 + Send393 + Sync394 + 'static,395 RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,396 RuntimeApi::RuntimeApi: LookaheadApiDep,397 Runtime: RuntimeInstance,398 ExecutorDispatch: NativeExecutionDispatch + 'static,399{400 let parachain_config = prepare_node_config(parachain_config);401402 let params = new_partial::<Runtime, RuntimeApi, ExecutorDispatch, _>(403 ¶chain_config,404 parachain_build_import_queue,405 )?;406 let OtherPartial {407 mut telemetry,408 telemetry_worker_handle,409 eth_filter_pool,410 eth_backend,411 } = params.other;412 let net_config = sc_network::config::FullNetworkConfiguration::new(¶chain_config.network);413414 let client = params.client.clone();415 let backend = params.backend.clone();416 let mut task_manager = params.task_manager;417418 let (relay_chain_interface, collator_key) = build_relay_chain_interface(419 polkadot_config,420 ¶chain_config,421 telemetry_worker_handle,422 &mut task_manager,423 collator_options.clone(),424 hwbench.clone(),425 )426 .await427 .map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?;428429 let validator = parachain_config.role.is_authority();430 let prometheus_registry = parachain_config.prometheus_registry().cloned();431 let transaction_pool = params.transaction_pool.clone();432 let import_queue_service = params.import_queue.service();433434 let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) =435 cumulus_client_service::build_network(cumulus_client_service::BuildNetworkParams {436 parachain_config: ¶chain_config,437 net_config,438 client: client.clone(),439 transaction_pool: transaction_pool.clone(),440 para_id,441 spawn_handle: task_manager.spawn_handle(),442 relay_chain_interface: relay_chain_interface.clone(),443 import_queue: params.import_queue,444 445 sybil_resistance_level: CollatorSybilResistance::Resistant,446 })447 .await?;448449 450 let fee_history_cache: FeeHistoryCache = Arc::new(Mutex::new(BTreeMap::new()));451 let fee_history_limit = 2048;452453 let eth_pubsub_notification_sinks: Arc<454 EthereumBlockNotificationSinks<fc_mapping_sync::EthereumBlockNotification<Block>>,455 > = Default::default();456457 let overrides = overrides_handle(client.clone());458 let eth_block_data_cache = spawn_frontier_tasks(459 FrontierTaskParams {460 client: client.clone(),461 substrate_backend: backend.clone(),462 eth_filter_pool: eth_filter_pool.clone(),463 eth_backend: eth_backend.clone(),464 fee_history_limit,465 fee_history_cache: fee_history_cache.clone(),466 task_manager: &task_manager,467 prometheus_registry: prometheus_registry.clone(),468 overrides: overrides.clone(),469 sync_strategy: SyncStrategy::Parachain,470 },471 sync_service.clone(),472 eth_pubsub_notification_sinks.clone(),473 );474475 476 let rpc_builder = Box::new({477 clone!(478 client,479 backend,480 eth_backend,481 eth_pubsub_notification_sinks,482 fee_history_cache,483 eth_block_data_cache,484 overrides,485 transaction_pool,486 network,487 sync_service,488 );489 move |deny_unsafe, subscription_task_executor: SubscriptionTaskExecutor| {490 clone!(491 backend,492 eth_block_data_cache,493 client,494 eth_backend,495 eth_filter_pool,496 eth_pubsub_notification_sinks,497 fee_history_cache,498 eth_block_data_cache,499 network,500 transaction_pool,501 overrides,502 );503504 #[cfg(not(feature = "pov-estimate"))]505 let _ = backend;506507 let mut rpc_handle = RpcModule::new(());508509 let full_deps = FullDeps {510 client: client.clone(),511512 #[cfg(feature = "pov-estimate")]513 exec_params: uc_rpc::pov_estimate::ExecutorParams {514 wasm_method: parachain_config.wasm_method,515 default_heap_pages: parachain_config.default_heap_pages,516 max_runtime_instances: parachain_config.max_runtime_instances,517 runtime_cache_size: parachain_config.runtime_cache_size,518 },519520 #[cfg(feature = "pov-estimate")]521 backend,522523 deny_unsafe,524 pool: transaction_pool.clone(),525 };526527 create_full::<_, _, Runtime, _>(&mut rpc_handle, full_deps)?;528529 let eth_deps = EthDeps {530 client,531 graph: transaction_pool.pool().clone(),532 pool: transaction_pool,533 is_authority: validator,534 network,535 eth_backend,536 537 max_past_logs: 10000,538 fee_history_limit,539 fee_history_cache,540 eth_block_data_cache,541 542 enable_dev_signer: false,543 eth_filter_pool,544 eth_pubsub_notification_sinks,545 overrides,546 sync: sync_service.clone(),547 pending_create_inherent_data_providers: |_, ()| async move {548 Ok(ethereum_parachain_inherent())549 },550 };551552 create_eth::<553 _,554 _,555 _,556 _,557 _,558 _,559 DefaultEthConfig<FullClient<RuntimeApi, ExecutorDispatch>>,560 >(561 &mut rpc_handle,562 eth_deps,563 subscription_task_executor.clone(),564 )?;565566 Ok(rpc_handle)567 }568 });569570 sc_service::spawn_tasks(sc_service::SpawnTasksParams {571 rpc_builder,572 client: client.clone(),573 transaction_pool: transaction_pool.clone(),574 task_manager: &mut task_manager,575 config: parachain_config,576 keystore: params.keystore_container.keystore(),577 backend: backend.clone(),578 network,579 sync_service: sync_service.clone(),580 system_rpc_tx,581 telemetry: telemetry.as_mut(),582 tx_handler_controller,583 })?;584585 if let Some(hwbench) = hwbench {586 sc_sysinfo::print_hwbench(&hwbench);587588 if let Some(ref mut telemetry) = telemetry {589 let telemetry_handle = telemetry.handle();590 task_manager.spawn_handle().spawn(591 "telemetry_hwbench",592 None,593 sc_sysinfo::initialize_hwbench_telemetry(telemetry_handle, hwbench),594 );595 }596 }597598 let announce_block = {599 let sync_service = sync_service.clone();600 Arc::new(Box::new(move |hash, data| {601 sync_service.announce_block(hash, data)602 }))603 };604605 let relay_chain_slot_duration = Duration::from_secs(6);606607 let overseer_handle = relay_chain_interface608 .overseer_handle()609 .map_err(|e| sc_service::Error::Application(Box::new(e)))?;610611 start_relay_chain_tasks(StartRelayChainTasksParams {612 client: client.clone(),613 announce_block: announce_block.clone(),614 para_id,615 relay_chain_interface: relay_chain_interface.clone(),616 task_manager: &mut task_manager,617 da_recovery_profile: if validator {618 DARecoveryProfile::Collator619 } else {620 DARecoveryProfile::FullNode621 },622 import_queue: import_queue_service,623 relay_chain_slot_duration,624 recovery_handle: Box::new(overseer_handle.clone()),625 sync_service: sync_service.clone(),626 })?;627628 if validator {629 start_consensus(630 client.clone(),631 transaction_pool,632 StartConsensusParameters {633 backend: backend.clone(),634 prometheus_registry: prometheus_registry.as_ref(),635 telemetry: telemetry.as_ref().map(|t| t.handle()),636 task_manager: &task_manager,637 relay_chain_interface: relay_chain_interface.clone(),638 sync_oracle: sync_service,639 keystore: params.keystore_container.keystore(),640 overseer_handle,641 relay_chain_slot_duration,642 para_id,643 collator_key: collator_key.expect("cli args do not allow this"),644 announce_block,645 },646 )?;647 }648649 start_network.start_network();650651 Ok((task_manager, client))652}653654655pub fn parachain_build_import_queue<Runtime, RuntimeApi, ExecutorDispatch>(656 client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,657 backend: Arc<FullBackend>,658 config: &Configuration,659 telemetry: Option<TelemetryHandle>,660 task_manager: &TaskManager,661) -> Result<sc_consensus::DefaultImportQueue<Block>, sc_service::Error>662where663 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>664 + Send665 + Sync666 + 'static,667 RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,668 Runtime: RuntimeInstance,669 ExecutorDispatch: NativeExecutionDispatch + 'static,670{671 let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;672673 let block_import = ParachainBlockImport::new(client.clone(), backend);674675 cumulus_client_consensus_aura::import_queue::<676 sp_consensus_aura::sr25519::AuthorityPair,677 _,678 _,679 _,680 _,681 _,682 >(cumulus_client_consensus_aura::ImportQueueParams {683 block_import,684 client,685 create_inherent_data_providers: move |_, _| async move {686 let time = sp_timestamp::InherentDataProvider::from_system_time();687688 let slot =689 sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(690 *time,691 slot_duration,692 );693694 Ok((slot, time))695 },696 registry: config.prometheus_registry(),697 spawner: &task_manager.spawn_essential_handle(),698 telemetry,699 })700 .map_err(Into::into)701}702703pub struct StartConsensusParameters<'a> {704 backend: Arc<FullBackend>,705 prometheus_registry: Option<&'a Registry>,706 telemetry: Option<TelemetryHandle>,707 task_manager: &'a TaskManager,708 relay_chain_interface: Arc<dyn RelayChainInterface>,709 sync_oracle: Arc<SyncingService<Block>>,710 keystore: KeystorePtr,711 overseer_handle: OverseerHandle,712 relay_chain_slot_duration: Duration,713 para_id: ParaId,714 collator_key: CollatorPair,715 announce_block: Arc<dyn Fn(Hash, Option<Vec<u8>>) + Send + Sync>,716}717718719#[allow(clippy::redundant_clone)]720pub fn start_consensus<ExecutorDispatch, RuntimeApi, Runtime>(721 client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,722 transaction_pool: Arc<723 sc_transaction_pool::FullPool<Block, FullClient<RuntimeApi, ExecutorDispatch>>,724 >,725 parameters: StartConsensusParameters<'_>,726) -> Result<(), sc_service::Error>727where728 ExecutorDispatch: NativeExecutionDispatch + 'static,729 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>730 + Send731 + Sync732 + 'static,733 RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,734 RuntimeApi::RuntimeApi: LookaheadApiDep,735 Runtime: RuntimeInstance,736{737 let StartConsensusParameters {738 backend,739 prometheus_registry,740 telemetry,741 task_manager,742 relay_chain_interface,743 sync_oracle,744 keystore,745 overseer_handle,746 relay_chain_slot_duration,747 para_id,748 collator_key,749 announce_block,750 } = parameters;751 let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;752753 let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(754 task_manager.spawn_handle(),755 client.clone(),756 transaction_pool,757 prometheus_registry,758 telemetry,759 );760 let proposer = Proposer::new(proposer_factory);761762 let collator_service = CollatorService::new(763 client.clone(),764 Arc::new(task_manager.spawn_handle()),765 announce_block,766 client.clone(),767 );768769 let block_import = ParachainBlockImport::new(client.clone(), backend.clone());770771 let params = BuildAuraConsensusParams {772 create_inherent_data_providers: move |_, ()| async move { Ok(()) },773 block_import,774 para_client: client.clone(),775 #[cfg(feature = "lookahead")]776 para_backend: backend,777 para_id,778 relay_client: relay_chain_interface,779 sync_oracle,780 keystore,781 #[cfg(not(feature = "lookahead"))]782 slot_duration,783 proposer,784 collator_service,785 786 #[cfg(not(feature = "lookahead"))]787 authoring_duration: Duration::from_millis(500),788 #[cfg(feature = "lookahead")]789 authoring_duration: Duration::from_millis(1500),790 overseer_handle,791 #[cfg(feature = "lookahead")]792 code_hash_provider: move |block_hash| {793 client794 .code_at(block_hash)795 .ok()796 .map(cumulus_primitives_core::relay_chain::ValidationCode)797 .map(|c| c.hash())798 },799 collator_key,800 relay_chain_slot_duration,801 #[cfg(not(feature = "lookahead"))]802 collation_request_receiver: None,803 #[cfg(feature = "lookahead")]804 reinitialize: false,805 };806807 task_manager.spawn_essential_handle().spawn(808 "aura",809 None,810 #[cfg(not(feature = "lookahead"))]811 run_aura::<_, AuraAuthorityPair, _, _, _, _, _, _, _>(params),812 #[cfg(feature = "lookahead")]813 run_aura::<_, AuraAuthorityPair, _, _, _, _, _, _, _, _, _>(params),814 );815 Ok(())816}817818fn dev_build_import_queue<RuntimeApi, ExecutorDispatch>(819 client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,820 _: Arc<FullBackend>,821 config: &Configuration,822 _: Option<TelemetryHandle>,823 task_manager: &TaskManager,824) -> Result<sc_consensus::DefaultImportQueue<Block>, sc_service::Error>825where826 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>827 + Send828 + Sync829 + 'static,830 RuntimeApi::RuntimeApi:831 sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> + sp_api::ApiExt<Block>,832 ExecutorDispatch: NativeExecutionDispatch + 'static,833{834 Ok(sc_consensus_manual_seal::import_queue(835 Box::new(client),836 &task_manager.spawn_essential_handle(),837 config.prometheus_registry(),838 ))839}840841pub struct OtherPartial {842 pub telemetry: Option<Telemetry>,843 pub telemetry_worker_handle: Option<TelemetryWorkerHandle>,844 pub eth_filter_pool: Option<FilterPool>,845 pub eth_backend: Arc<fc_db::kv::Backend<Block>>,846}847848struct DefaultEthConfig<C>(PhantomData<C>);849impl<C> EthConfig<Block, C> for DefaultEthConfig<C>850where851 C: StorageProvider<Block, FullBackend> + Sync + Send + 'static,852{853 type EstimateGasAdapter = ();854 type RuntimeStorageOverride = SystemAccountId32StorageOverride<Block, C, FullBackend>;855}856857858859pub fn start_dev_node<Runtime, RuntimeApi, ExecutorDispatch>(860 config: Configuration,861 autoseal_interval: u64,862 autoseal_finalize_delay: Option<u64>,863 disable_autoseal_on_tx: bool,864) -> sc_service::error::Result<TaskManager>865where866 Runtime: RuntimeInstance + Send + Sync + 'static,867 <Runtime as RuntimeInstance>::CrossAccountId: Serialize,868 for<'de> <Runtime as RuntimeInstance>::CrossAccountId: Deserialize<'de>,869 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>870 + Send871 + Sync872 + 'static,873 RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,874 ExecutorDispatch: NativeExecutionDispatch + 'static,875{876 use fc_consensus::FrontierBlockImport;877 use sc_consensus_manual_seal::{878 run_delayed_finalize, run_manual_seal, DelayedFinalizeParams, EngineCommand,879 ManualSealParams,880 };881882 let sc_service::PartialComponents {883 client,884 backend,885 mut task_manager,886 import_queue,887 keystore_container,888 select_chain: maybe_select_chain,889 transaction_pool,890 other:891 OtherPartial {892 telemetry,893 eth_filter_pool,894 eth_backend,895 telemetry_worker_handle: _,896 },897 } = new_partial::<Runtime, RuntimeApi, ExecutorDispatch, _>(898 &config,899 dev_build_import_queue::<RuntimeApi, ExecutorDispatch>,900 )?;901 let net_config = sc_network::config::FullNetworkConfiguration::new(&config.network);902 let prometheus_registry = config.prometheus_registry().cloned();903904 let (network, system_rpc_tx, tx_handler_controller, network_starter, sync_service) =905 sc_service::build_network(sc_service::BuildNetworkParams {906 config: &config,907 net_config,908 client: client.clone(),909 transaction_pool: transaction_pool.clone(),910 spawn_handle: task_manager.spawn_handle(),911 import_queue,912 block_announce_validator_builder: None,913 warp_sync_params: None,914 block_relay: None,915 })?;916917 let collator = config.role.is_authority();918919 let select_chain = maybe_select_chain;920921 if collator {922 let block_import = FrontierBlockImport::new(client.clone(), client.clone());923924 let env = sc_basic_authorship::ProposerFactory::new(925 task_manager.spawn_handle(),926 client.clone(),927 transaction_pool.clone(),928 prometheus_registry.as_ref(),929 telemetry.as_ref().map(|x| x.handle()),930 );931932 let transactions_commands_stream: Box<933 dyn Stream<Item = EngineCommand<Hash>> + Send + Sync + Unpin,934 > = Box::new(935 transaction_pool936 .pool()937 .validated_pool()938 .import_notification_stream()939 .filter(move |_| futures::future::ready(!disable_autoseal_on_tx))940 .map(|_| EngineCommand::SealNewBlock {941 create_empty: true,942 finalize: false,943 parent_hash: None,944 sender: None,945 }),946 );947948 let autoseal_interval = Box::pin(AutosealInterval::new(&config, autoseal_interval));949950 let idle_commands_stream: Box<951 dyn Stream<Item = EngineCommand<Hash>> + Send + Sync + Unpin,952 > = Box::new(autoseal_interval.map(|_| EngineCommand::SealNewBlock {953 create_empty: true,954 finalize: false,955 parent_hash: None,956 sender: None,957 }));958959 let commands_stream = select(transactions_commands_stream, idle_commands_stream);960961 let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;962 let client_set_aside_for_cidp = client.clone();963964 if let Some(delay_sec) = autoseal_finalize_delay {965 let spawn_handle = task_manager.spawn_handle();966967 task_manager.spawn_essential_handle().spawn_blocking(968 "finalization_task",969 Some("block-authoring"),970 run_delayed_finalize(DelayedFinalizeParams {971 client: client.clone(),972 delay_sec,973 spawn_handle,974 }),975 );976 }977978 task_manager.spawn_essential_handle().spawn_blocking(979 "authorship_task",980 Some("block-authoring"),981 run_manual_seal(ManualSealParams {982 block_import,983 env,984 client: client.clone(),985 pool: transaction_pool.clone(),986 commands_stream,987 select_chain: select_chain.clone(),988 consensus_data_provider: None,989 create_inherent_data_providers: move |block: Hash, ()| {990 let current_para_block = client_set_aside_for_cidp991 .number(block)992 .expect("Header lookup should succeed")993 .expect("Header passed in as parent should be present in backend.");994995 let client_for_xcm = client_set_aside_for_cidp.clone();996 async move {997 let time = sp_timestamp::InherentDataProvider::from_system_time();998999 let mocked_parachain = cumulus_client_parachain_inherent::MockValidationDataInherentDataProvider {1000 current_para_block,1001 relay_offset: 1000,1002 relay_blocks_per_para_block: 2,1003 para_blocks_per_relay_epoch: 0,1004 xcm_config: cumulus_client_parachain_inherent::MockXcmConfig::new(1005 &*client_for_xcm,1006 block,1007 Default::default(),1008 Default::default(),1009 ),1010 relay_randomness_config: (),1011 raw_downward_messages: vec![],1012 raw_horizontal_messages: vec![],1013 additional_key_values: None,1014 };10151016 let slot =1017 sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(1018 *time,1019 slot_duration,1020 );10211022 Ok((time, slot, mocked_parachain))1023 }1024 },1025 }),1026 );1027 }10281029 #[cfg(feature = "pov-estimate")]1030 let rpc_backend = backend.clone();10311032 1033 let fee_history_cache: FeeHistoryCache = Arc::new(Mutex::new(BTreeMap::new()));1034 let fee_history_limit = 2048;10351036 let eth_pubsub_notification_sinks: Arc<1037 EthereumBlockNotificationSinks<fc_mapping_sync::EthereumBlockNotification<Block>>,1038 > = Default::default();10391040 let overrides = overrides_handle(client.clone());1041 let eth_block_data_cache = spawn_frontier_tasks(1042 FrontierTaskParams {1043 client: client.clone(),1044 substrate_backend: backend.clone(),1045 eth_filter_pool: eth_filter_pool.clone(),1046 eth_backend: eth_backend.clone(),1047 fee_history_limit,1048 fee_history_cache: fee_history_cache.clone(),1049 task_manager: &task_manager,1050 prometheus_registry,1051 overrides: overrides.clone(),1052 sync_strategy: SyncStrategy::Normal,1053 },1054 sync_service.clone(),1055 eth_pubsub_notification_sinks.clone(),1056 );10571058 1059 let rpc_builder = Box::new({1060 clone!(1061 client,1062 backend,1063 eth_backend,1064 eth_pubsub_notification_sinks,1065 fee_history_cache,1066 eth_block_data_cache,1067 overrides,1068 transaction_pool,1069 network,1070 sync_service,1071 );1072 move |deny_unsafe, subscription_task_executor: SubscriptionTaskExecutor| {1073 clone!(1074 backend,1075 eth_block_data_cache,1076 client,1077 eth_backend,1078 eth_filter_pool,1079 eth_pubsub_notification_sinks,1080 fee_history_cache,1081 eth_block_data_cache,1082 network,1083 transaction_pool,1084 overrides,1085 );10861087 #[cfg(not(feature = "pov-estimate"))]1088 let _ = backend;10891090 let mut rpc_module = RpcModule::new(());10911092 let full_deps = FullDeps {1093 #[cfg(feature = "pov-estimate")]1094 exec_params: uc_rpc::pov_estimate::ExecutorParams {1095 wasm_method: config.wasm_method,1096 default_heap_pages: config.default_heap_pages,1097 max_runtime_instances: config.max_runtime_instances,1098 runtime_cache_size: config.runtime_cache_size,1099 },11001101 #[cfg(feature = "pov-estimate")]1102 backend,1103 1104 deny_unsafe,1105 client: client.clone(),1106 pool: transaction_pool.clone(),1107 };11081109 create_full::<_, _, Runtime, _>(&mut rpc_module, full_deps)?;11101111 let eth_deps = EthDeps {1112 client,1113 graph: transaction_pool.pool().clone(),1114 pool: transaction_pool,1115 is_authority: true,1116 network,1117 eth_backend,1118 1119 max_past_logs: 10000,1120 fee_history_limit,1121 fee_history_cache,1122 eth_block_data_cache,1123 1124 enable_dev_signer: false,1125 eth_filter_pool,1126 eth_pubsub_notification_sinks,1127 overrides,1128 sync: sync_service.clone(),1129 1130 pending_create_inherent_data_providers: |_, ()| async move {1131 Ok(ethereum_parachain_inherent())1132 },1133 };11341135 create_eth::<1136 _,1137 _,1138 _,1139 _,1140 _,1141 _,1142 DefaultEthConfig<FullClient<RuntimeApi, ExecutorDispatch>>,1143 >(1144 &mut rpc_module,1145 eth_deps,1146 subscription_task_executor.clone(),1147 )?;11481149 Ok(rpc_module)1150 }1151 });11521153 sc_service::spawn_tasks(sc_service::SpawnTasksParams {1154 network,1155 sync_service,1156 client,1157 keystore: keystore_container.keystore(),1158 task_manager: &mut task_manager,1159 transaction_pool,1160 rpc_builder,1161 backend,1162 system_rpc_tx,1163 config,1164 telemetry: None,1165 tx_handler_controller,1166 })?;11671168 network_starter.start_network();1169 Ok(task_manager)1170}11711172fn overrides_handle<C, BE>(client: Arc<C>) -> Arc<OverrideHandle<Block>>1173where1174 C: ProvideRuntimeApi<Block> + StorageProvider<Block, BE> + AuxStore,1175 C: HeaderBackend<Block> + HeaderMetadata<Block, Error = BlockChainError>,1176 C: Send + Sync + 'static,1177 C::Api: fp_rpc::EthereumRuntimeRPCApi<Block>,1178 BE: Backend<Block> + 'static,1179 BE::State: StateBackend<BlakeTwo256>,1180{1181 let mut overrides_map = BTreeMap::new();1182 overrides_map.insert(1183 EthereumStorageSchema::V1,1184 Box::new(SchemaV1Override::new(client.clone())) as Box<dyn StorageOverride<_> + 'static>,1185 );1186 overrides_map.insert(1187 EthereumStorageSchema::V2,1188 Box::new(SchemaV2Override::new(client.clone())) as Box<dyn StorageOverride<_> + 'static>,1189 );1190 overrides_map.insert(1191 EthereumStorageSchema::V3,1192 Box::new(SchemaV3Override::new(client.clone())) as Box<dyn StorageOverride<_> + 'static>,1193 );11941195 Arc::new(OverrideHandle {1196 schemas: overrides_map,1197 fallback: Box::new(RuntimeApiStorageOverride::new(client)),1198 })1199}12001201pub struct FrontierTaskParams<'a, C, B> {1202 pub task_manager: &'a TaskManager,1203 pub client: Arc<C>,1204 pub substrate_backend: Arc<B>,1205 pub eth_backend: Arc<fc_db::kv::Backend<Block>>,1206 pub eth_filter_pool: Option<FilterPool>,1207 pub overrides: Arc<OverrideHandle<Block>>,1208 pub fee_history_limit: u64,1209 pub fee_history_cache: FeeHistoryCache,1210 pub sync_strategy: SyncStrategy,1211 pub prometheus_registry: Option<Registry>,1212}12131214pub fn spawn_frontier_tasks<C, B>(1215 params: FrontierTaskParams<C, B>,1216 sync: Arc<SyncingService<Block>>,1217 pubsub_notification_sinks: Arc<1218 EthereumBlockNotificationSinks<fc_mapping_sync::EthereumBlockNotification<Block>>,1219 >,1220) -> Arc<EthBlockDataCacheTask<Block>>1221where1222 C: ProvideRuntimeApi<Block> + BlockOf,1223 C: HeaderBackend<Block> + HeaderMetadata<Block, Error = BlockChainError> + 'static,1224 C: BlockchainEvents<Block> + StorageProvider<Block, B>,1225 C: Send + Sync + 'static,1226 C::Api: EthereumRuntimeRPCApi<Block>,1227 C::Api: BlockBuilder<Block>,1228 B: Backend<Block> + 'static,1229 B::State: StateBackend<BlakeTwo256>,1230{1231 let FrontierTaskParams {1232 task_manager,1233 client,1234 substrate_backend,1235 eth_backend,1236 eth_filter_pool,1237 overrides,1238 fee_history_limit,1239 fee_history_cache,1240 sync_strategy,1241 prometheus_registry,1242 } = params;1243 1244 1245 params.task_manager.spawn_essential_handle().spawn(1246 "frontier-mapping-sync-worker",1247 Some("frontier"),1248 MappingSyncWorker::new(1249 client.import_notification_stream(),1250 Duration::new(6, 0),1251 client.clone(),1252 substrate_backend,1253 overrides.clone(),1254 eth_backend,1255 3,1256 0,1257 sync_strategy,1258 sync,1259 pubsub_notification_sinks,1260 )1261 .for_each(|()| futures::future::ready(())),1262 );12631264 1265 1266 if let Some(eth_filter_pool) = eth_filter_pool {1267 1268 const FILTER_RETAIN_THRESHOLD: u64 = 100;1269 params.task_manager.spawn_essential_handle().spawn(1270 "frontier-filter-pool",1271 Some("frontier"),1272 EthTask::filter_pool_task(client.clone(), eth_filter_pool, FILTER_RETAIN_THRESHOLD),1273 );1274 }12751276 1277 params.task_manager.spawn_essential_handle().spawn(1278 "frontier-fee-history",1279 Some("frontier"),1280 EthTask::fee_history_task(1281 client,1282 overrides.clone(),1283 fee_history_cache,1284 fee_history_limit,1285 ),1286 );12871288 Arc::new(EthBlockDataCacheTask::new(1289 task_manager.spawn_handle(),1290 overrides,1291 50,1292 50,1293 prometheus_registry,1294 ))1295}