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, DARecoveryProfile,40 StartRelayChainTasksParams,41};42use cumulus_primitives_core::ParaId;43use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface};44use fc_mapping_sync::{kv::MappingSyncWorker, EthereumBlockNotificationSinks, SyncStrategy};45use fc_rpc::{46 frontier_backend_client::SystemAccountId32StorageOverride, EthBlockDataCacheTask, EthConfig,47 EthTask, OverrideHandle, RuntimeApiStorageOverride, SchemaV1Override, SchemaV2Override,48 SchemaV3Override, StorageOverride,49};50use fc_rpc_core::types::{FeeHistoryCache, FilterPool};51use fp_rpc::EthereumRuntimeRPCApi;52use fp_storage::EthereumStorageSchema;53use futures::{54 stream::select,55 task::{Context, Poll},56 Stream, StreamExt,57};58use jsonrpsee::RpcModule;59use polkadot_service::CollatorPair;60use sc_client_api::{AuxStore, Backend, BlockOf, BlockchainEvents, StorageProvider};61use sc_consensus::ImportQueue;62use sc_executor::{NativeElseWasmExecutor, NativeExecutionDispatch};63use sc_network::NetworkBlock;64use sc_network_sync::SyncingService;65use sc_rpc::SubscriptionTaskExecutor;66use sc_service::{Configuration, PartialComponents, TaskManager};67use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle};68use serde::{Deserialize, Serialize};69use sp_api::ProvideRuntimeApi;70use sp_block_builder::BlockBuilder;71use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};72use sp_consensus_aura::sr25519::AuthorityPair as AuraAuthorityPair;73use sp_keystore::KeystorePtr;74use sp_state_machine::Backend as StateBackend;75use substrate_prometheus_endpoint::Registry;76use tokio::time::Interval;77use up_common::types::{opaque::*, Nonce};7879pub type ParachainHostFunctions = (80 sp_io::SubstrateHostFunctions,81 cumulus_client_service::storage_proof_size::HostFunctions,82);8384use crate::{85 chain_spec::RuntimeIdentification,86 rpc::{create_eth, create_full, EthDeps, FullDeps},87};888990#[cfg(feature = "unique-runtime")]91pub struct UniqueRuntimeExecutor;9293#[cfg(feature = "quartz-runtime")]9495pub struct QuartzRuntimeExecutor;969798pub struct OpalRuntimeExecutor;99100#[cfg(feature = "unique-runtime")]101impl NativeExecutionDispatch for UniqueRuntimeExecutor {102 103 #[cfg(feature = "runtime-benchmarks")]104 type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;105 106 #[cfg(not(feature = "runtime-benchmarks"))]107 type ExtendHostFunctions = ParachainHostFunctions;108109 fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {110 unique_runtime::api::dispatch(method, data)111 }112113 fn native_version() -> sc_executor::NativeVersion {114 unique_runtime::native_version()115 }116}117118#[cfg(feature = "quartz-runtime")]119impl NativeExecutionDispatch for QuartzRuntimeExecutor {120 121 #[cfg(feature = "runtime-benchmarks")]122 type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;123 124 #[cfg(not(feature = "runtime-benchmarks"))]125 type ExtendHostFunctions = ParachainHostFunctions;126127 fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {128 quartz_runtime::api::dispatch(method, data)129 }130131 fn native_version() -> sc_executor::NativeVersion {132 quartz_runtime::native_version()133 }134}135136impl NativeExecutionDispatch for OpalRuntimeExecutor {137 138 #[cfg(feature = "runtime-benchmarks")]139 type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;140 141 #[cfg(not(feature = "runtime-benchmarks"))]142 type ExtendHostFunctions = ParachainHostFunctions;143144 fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {145 opal_runtime::api::dispatch(method, data)146 }147148 fn native_version() -> sc_executor::NativeVersion {149 opal_runtime::native_version()150 }151}152153pub struct AutosealInterval {154 interval: Interval,155}156157impl AutosealInterval {158 pub fn new(config: &Configuration, interval: u64) -> Self {159 let _tokio_runtime = config.tokio_handle.enter();160 let interval = tokio::time::interval(Duration::from_millis(interval));161162 Self { interval }163 }164}165166impl Stream for AutosealInterval {167 type Item = tokio::time::Instant;168169 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {170 self.interval.poll_tick(cx).map(Some)171 }172}173174pub fn open_frontier_backend<C: HeaderBackend<Block>>(175 client: Arc<C>,176 config: &Configuration,177) -> Result<Arc<fc_db::kv::Backend<Block>>, String> {178 let config_dir = config.base_path.config_dir(config.chain_spec.id());179 let database_dir = config_dir.join("frontier").join("db");180181 Ok(Arc::new(fc_db::kv::Backend::<Block>::new(182 client,183 &fc_db::kv::DatabaseSettings {184 source: fc_db::DatabaseSource::RocksDb {185 path: database_dir,186 cache_size: 0,187 },188 },189 )?))190}191192type FullClient<RuntimeApi, ExecutorDispatch> =193 sc_service::TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ExecutorDispatch>>;194type FullBackend = sc_service::TFullBackend<Block>;195type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;196type ParachainBlockImport<RuntimeApi, ExecutorDispatch> =197 TParachainBlockImport<Block, Arc<FullClient<RuntimeApi, ExecutorDispatch>>, FullBackend>;198199200macro_rules! ez_bounds {201 ($vis:vis trait $name:ident$(<$($gen:ident $(: $($(+)? $bound:path)*)?),* $(,)?>)? $(:)? $($(+)? $super:path)* {}) => {202 $vis trait $name $(<$($gen $(: $($bound+)*)?,)*>)?: $($super +)* {}203 impl<T, $($($gen $(: $($bound+)*)?,)*)?> $name$(<$($gen,)*>)? for T204 where T: $($super +)* {}205 }206}207ez_bounds!(208 pub trait RuntimeApiDep<Runtime: RuntimeInstance>:209 sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>210 + sp_consensus_aura::AuraApi<Block, AuraId>211 + fp_rpc::EthereumRuntimeRPCApi<Block>212 + sp_session::SessionKeys<Block>213 + sp_block_builder::BlockBuilder<Block>214 + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>215 + sp_api::ApiExt<Block>216 + up_rpc::UniqueApi<Block, Runtime::CrossAccountId, AccountId>217 + app_promotion_rpc::AppPromotionApi<Block, BlockNumber, Runtime::CrossAccountId, AccountId>218 + up_pov_estimate_rpc::PovEstimateApi<Block>219 + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>220 + sp_api::Metadata<Block>221 + sp_offchain::OffchainWorkerApi<Block>222 + cumulus_primitives_core::CollectCollationInfo<Block>223 224 + fp_rpc::ConvertTransactionRuntimeApi<Block>225 {226 }227);228#[cfg(not(feature = "lookahead"))]229ez_bounds!(230 pub trait LookaheadApiDep {}231);232#[cfg(feature = "lookahead")]233ez_bounds!(234 pub trait LookaheadApiDep: cumulus_primitives_aura::AuraUnincludedSegmentApi<Block> {}235);236237238239240241#[allow(clippy::type_complexity)]242pub fn new_partial<Runtime, RuntimeApi, ExecutorDispatch, BIQ>(243 config: &Configuration,244 build_import_queue: BIQ,245) -> Result<246 PartialComponents<247 FullClient<RuntimeApi, ExecutorDispatch>,248 FullBackend,249 FullSelectChain,250 sc_consensus::DefaultImportQueue<Block>,251 sc_transaction_pool::FullPool<Block, FullClient<RuntimeApi, ExecutorDispatch>>,252 OtherPartial,253 >,254 sc_service::Error,255>256where257 sc_client_api::StateBackendFor<FullBackend, Block>: StateBackend<BlakeTwo256>,258 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>259 + Send260 + Sync261 + 'static,262 RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,263 Runtime: RuntimeInstance,264 ExecutorDispatch: NativeExecutionDispatch + 'static,265 BIQ: FnOnce(266 Arc<FullClient<RuntimeApi, ExecutorDispatch>>,267 Arc<FullBackend>,268 &Configuration,269 Option<TelemetryHandle>,270 &TaskManager,271 ) -> Result<sc_consensus::DefaultImportQueue<Block>, sc_service::Error>,272{273 let telemetry = config274 .telemetry_endpoints275 .clone()276 .filter(|x| !x.is_empty())277 .map(|endpoints| -> Result<_, sc_telemetry::Error> {278 let worker = TelemetryWorker::new(16)?;279 let telemetry = worker.handle().new_telemetry(endpoints);280 Ok((worker, telemetry))281 })282 .transpose()?;283284 let executor = sc_service::new_native_or_wasm_executor(config);285286 let (client, backend, keystore_container, task_manager) =287 sc_service::new_full_parts::<Block, RuntimeApi, _>(288 config,289 telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),290 executor,291 )?;292 let client = Arc::new(client);293294 let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle());295296 let telemetry = telemetry.map(|(worker, telemetry)| {297 task_manager298 .spawn_handle()299 .spawn("telemetry", None, worker.run());300 telemetry301 });302303 let select_chain = sc_consensus::LongestChain::new(backend.clone());304305 let transaction_pool = sc_transaction_pool::BasicPool::new_full(306 config.transaction_pool.clone(),307 config.role.is_authority().into(),308 config.prometheus_registry(),309 task_manager.spawn_essential_handle(),310 client.clone(),311 );312313 let eth_filter_pool: Option<FilterPool> = Some(Arc::new(Mutex::new(BTreeMap::new())));314315 let eth_backend = open_frontier_backend(client.clone(), config)?;316317 let import_queue = build_import_queue(318 client.clone(),319 backend.clone(),320 config,321 telemetry.as_ref().map(|telemetry| telemetry.handle()),322 &task_manager,323 )?;324325 let params = PartialComponents {326 backend,327 client,328 import_queue,329 keystore_container,330 task_manager,331 transaction_pool,332 select_chain,333 other: OtherPartial {334 telemetry,335 eth_filter_pool,336 eth_backend,337 telemetry_worker_handle,338 },339 };340341 Ok(params)342}343344macro_rules! clone {345 ($($i:ident),* $(,)?) => {346 $(347 let $i = $i.clone();348 )*349 };350}351352353354355#[sc_tracing::logging::prefix_logs_with("Parachain")]356pub async fn start_node<Runtime, RuntimeApi, ExecutorDispatch>(357 parachain_config: Configuration,358 polkadot_config: Configuration,359 collator_options: CollatorOptions,360 para_id: ParaId,361 hwbench: Option<sc_sysinfo::HwBench>,362) -> sc_service::error::Result<(TaskManager, Arc<FullClient<RuntimeApi, ExecutorDispatch>>)>363where364 sc_client_api::StateBackendFor<FullBackend, Block>: StateBackend<BlakeTwo256>,365 Runtime: RuntimeInstance + Send + Sync + 'static,366 <Runtime as RuntimeInstance>::CrossAccountId: Serialize,367 for<'de> <Runtime as RuntimeInstance>::CrossAccountId: Deserialize<'de>,368 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>369 + Send370 + Sync371 + 'static,372 RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,373 RuntimeApi::RuntimeApi: LookaheadApiDep,374 Runtime: RuntimeInstance,375 ExecutorDispatch: NativeExecutionDispatch + 'static,376{377 let parachain_config = prepare_node_config(parachain_config);378379 let params = new_partial::<Runtime, RuntimeApi, ExecutorDispatch, _>(380 ¶chain_config,381 parachain_build_import_queue,382 )?;383 let OtherPartial {384 mut telemetry,385 telemetry_worker_handle,386 eth_filter_pool,387 eth_backend,388 } = params.other;389 let net_config = sc_network::config::FullNetworkConfiguration::new(¶chain_config.network);390391 let client = params.client.clone();392 let backend = params.backend.clone();393 let mut task_manager = params.task_manager;394395 let (relay_chain_interface, collator_key) = build_relay_chain_interface(396 polkadot_config,397 ¶chain_config,398 telemetry_worker_handle,399 &mut task_manager,400 collator_options.clone(),401 hwbench.clone(),402 )403 .await404 .map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?;405406 407 let block_announce_validator =408 cumulus_client_network::AssumeSybilResistance::allow_seconded_messages();409410 let validator = parachain_config.role.is_authority();411 let prometheus_registry = parachain_config.prometheus_registry().cloned();412 let transaction_pool = params.transaction_pool.clone();413 let import_queue_service = params.import_queue.service();414415 let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) =416 sc_service::build_network(sc_service::BuildNetworkParams {417 config: ¶chain_config,418 net_config,419 client: client.clone(),420 transaction_pool: transaction_pool.clone(),421 spawn_handle: task_manager.spawn_handle(),422 import_queue: params.import_queue,423 block_announce_validator_builder: Some(Box::new(|_| {424 Box::new(block_announce_validator)425 })),426 warp_sync_params: None,427 block_relay: None,428 })?;429430 let select_chain = params.select_chain.clone();431432 let runtime_id = parachain_config.chain_spec.runtime_id();433434 435 let fee_history_cache: FeeHistoryCache = Arc::new(Mutex::new(BTreeMap::new()));436 let fee_history_limit = 2048;437438 let eth_pubsub_notification_sinks: Arc<439 EthereumBlockNotificationSinks<fc_mapping_sync::EthereumBlockNotification<Block>>,440 > = Default::default();441442 let overrides = overrides_handle(client.clone());443 let eth_block_data_cache = spawn_frontier_tasks(444 FrontierTaskParams {445 client: client.clone(),446 substrate_backend: backend.clone(),447 eth_filter_pool: eth_filter_pool.clone(),448 eth_backend: eth_backend.clone(),449 fee_history_limit,450 fee_history_cache: fee_history_cache.clone(),451 task_manager: &task_manager,452 prometheus_registry: prometheus_registry.clone(),453 overrides: overrides.clone(),454 sync_strategy: SyncStrategy::Parachain,455 },456 sync_service.clone(),457 eth_pubsub_notification_sinks.clone(),458 );459460 461 let rpc_builder = Box::new({462 clone!(463 client,464 backend,465 eth_backend,466 eth_pubsub_notification_sinks,467 fee_history_cache,468 eth_block_data_cache,469 overrides,470 transaction_pool,471 network,472 sync_service,473 );474 move |deny_unsafe, subscription_task_executor: SubscriptionTaskExecutor| {475 clone!(476 backend,477 eth_block_data_cache,478 client,479 eth_backend,480 eth_filter_pool,481 eth_pubsub_notification_sinks,482 fee_history_cache,483 eth_block_data_cache,484 network,485 runtime_id,486 transaction_pool,487 select_chain,488 overrides,489 );490491 #[cfg(not(feature = "pov-estimate"))]492 let _ = backend;493494 let mut rpc_handle = RpcModule::new(());495496 let full_deps = FullDeps {497 client: client.clone(),498 runtime_id,499500 #[cfg(feature = "pov-estimate")]501 exec_params: uc_rpc::pov_estimate::ExecutorParams {502 wasm_method: parachain_config.wasm_method,503 default_heap_pages: parachain_config.default_heap_pages,504 max_runtime_instances: parachain_config.max_runtime_instances,505 runtime_cache_size: parachain_config.runtime_cache_size,506 },507508 #[cfg(feature = "pov-estimate")]509 backend,510511 deny_unsafe,512 pool: transaction_pool.clone(),513 select_chain,514 };515516 create_full::<_, _, _, Runtime, _>(&mut rpc_handle, full_deps)?;517518 let eth_deps = EthDeps {519 client,520 graph: transaction_pool.pool().clone(),521 pool: transaction_pool,522 is_authority: validator,523 network,524 eth_backend,525 526 max_past_logs: 10000,527 fee_history_limit,528 fee_history_cache,529 eth_block_data_cache,530 531 enable_dev_signer: false,532 eth_filter_pool,533 eth_pubsub_notification_sinks,534 overrides,535 sync: sync_service.clone(),536 pending_create_inherent_data_providers: |_, ()| async move { Ok(()) },537 };538539 create_eth::<540 _,541 _,542 _,543 _,544 _,545 _,546 DefaultEthConfig<FullClient<RuntimeApi, ExecutorDispatch>>,547 >(548 &mut rpc_handle,549 eth_deps,550 subscription_task_executor.clone(),551 )?;552553 Ok(rpc_handle)554 }555 });556557 sc_service::spawn_tasks(sc_service::SpawnTasksParams {558 rpc_builder,559 client: client.clone(),560 transaction_pool: transaction_pool.clone(),561 task_manager: &mut task_manager,562 config: parachain_config,563 keystore: params.keystore_container.keystore(),564 backend: backend.clone(),565 network,566 sync_service: sync_service.clone(),567 system_rpc_tx,568 telemetry: telemetry.as_mut(),569 tx_handler_controller,570 })?;571572 if let Some(hwbench) = hwbench {573 sc_sysinfo::print_hwbench(&hwbench);574575 if let Some(ref mut telemetry) = telemetry {576 let telemetry_handle = telemetry.handle();577 task_manager.spawn_handle().spawn(578 "telemetry_hwbench",579 None,580 sc_sysinfo::initialize_hwbench_telemetry(telemetry_handle, hwbench),581 );582 }583 }584585 let announce_block = {586 let sync_service = sync_service.clone();587 Arc::new(Box::new(move |hash, data| {588 sync_service.announce_block(hash, data)589 }))590 };591592 let relay_chain_slot_duration = Duration::from_secs(6);593594 let overseer_handle = relay_chain_interface595 .overseer_handle()596 .map_err(|e| sc_service::Error::Application(Box::new(e)))?;597598 start_relay_chain_tasks(StartRelayChainTasksParams {599 client: client.clone(),600 announce_block: announce_block.clone(),601 para_id,602 relay_chain_interface: relay_chain_interface.clone(),603 task_manager: &mut task_manager,604 da_recovery_profile: if validator {605 DARecoveryProfile::Collator606 } else {607 DARecoveryProfile::FullNode608 },609 import_queue: import_queue_service,610 relay_chain_slot_duration,611 recovery_handle: Box::new(overseer_handle.clone()),612 sync_service: sync_service.clone(),613 })?;614615 if validator {616 start_consensus(617 client.clone(),618 transaction_pool,619 StartConsensusParameters {620 backend: backend.clone(),621 prometheus_registry: prometheus_registry.as_ref(),622 telemetry: telemetry.as_ref().map(|t| t.handle()),623 task_manager: &task_manager,624 relay_chain_interface: relay_chain_interface.clone(),625 sync_oracle: sync_service,626 keystore: params.keystore_container.keystore(),627 overseer_handle,628 relay_chain_slot_duration,629 para_id,630 collator_key: collator_key.expect("cli args do not allow this"),631 announce_block,632 },633 )?;634 }635636 start_network.start_network();637638 Ok((task_manager, client))639}640641642pub fn parachain_build_import_queue<Runtime, RuntimeApi, ExecutorDispatch>(643 client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,644 backend: Arc<FullBackend>,645 config: &Configuration,646 telemetry: Option<TelemetryHandle>,647 task_manager: &TaskManager,648) -> Result<sc_consensus::DefaultImportQueue<Block>, sc_service::Error>649where650 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>651 + Send652 + Sync653 + 'static,654 RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,655 Runtime: RuntimeInstance,656 ExecutorDispatch: NativeExecutionDispatch + 'static,657{658 let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;659660 let block_import = ParachainBlockImport::new(client.clone(), backend);661662 cumulus_client_consensus_aura::import_queue::<663 sp_consensus_aura::sr25519::AuthorityPair,664 _,665 _,666 _,667 _,668 _,669 >(cumulus_client_consensus_aura::ImportQueueParams {670 block_import,671 client,672 create_inherent_data_providers: move |_, _| async move {673 let time = sp_timestamp::InherentDataProvider::from_system_time();674675 let slot =676 sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(677 *time,678 slot_duration,679 );680681 Ok((slot, time))682 },683 registry: config.prometheus_registry(),684 spawner: &task_manager.spawn_essential_handle(),685 telemetry,686 })687 .map_err(Into::into)688}689690pub struct StartConsensusParameters<'a> {691 backend: Arc<FullBackend>,692 prometheus_registry: Option<&'a Registry>,693 telemetry: Option<TelemetryHandle>,694 task_manager: &'a TaskManager,695 relay_chain_interface: Arc<dyn RelayChainInterface>,696 sync_oracle: Arc<SyncingService<Block>>,697 keystore: KeystorePtr,698 overseer_handle: OverseerHandle,699 relay_chain_slot_duration: Duration,700 para_id: ParaId,701 collator_key: CollatorPair,702 announce_block: Arc<dyn Fn(Hash, Option<Vec<u8>>) + Send + Sync>,703}704705706#[allow(clippy::redundant_clone)]707pub fn start_consensus<ExecutorDispatch, RuntimeApi, Runtime>(708 client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,709 transaction_pool: Arc<710 sc_transaction_pool::FullPool<Block, FullClient<RuntimeApi, ExecutorDispatch>>,711 >,712 parameters: StartConsensusParameters<'_>,713) -> Result<(), sc_service::Error>714where715 ExecutorDispatch: NativeExecutionDispatch + 'static,716 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>717 + Send718 + Sync719 + 'static,720 RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,721 RuntimeApi::RuntimeApi: LookaheadApiDep,722 Runtime: RuntimeInstance,723{724 let StartConsensusParameters {725 backend,726 prometheus_registry,727 telemetry,728 task_manager,729 relay_chain_interface,730 sync_oracle,731 keystore,732 overseer_handle,733 relay_chain_slot_duration,734 para_id,735 collator_key,736 announce_block,737 } = parameters;738 let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;739740 let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(741 task_manager.spawn_handle(),742 client.clone(),743 transaction_pool,744 prometheus_registry,745 telemetry,746 );747 let proposer = Proposer::new(proposer_factory);748749 let collator_service = CollatorService::new(750 client.clone(),751 Arc::new(task_manager.spawn_handle()),752 announce_block,753 client.clone(),754 );755756 let block_import = ParachainBlockImport::new(client.clone(), backend.clone());757758 let params = BuildAuraConsensusParams {759 create_inherent_data_providers: move |_, ()| async move { Ok(()) },760 block_import,761 para_client: client.clone(),762 #[cfg(feature = "lookahead")]763 para_backend: backend,764 para_id,765 relay_client: relay_chain_interface,766 sync_oracle,767 keystore,768 slot_duration,769 proposer,770 collator_service,771 772 #[cfg(not(feature = "lookahead"))]773 authoring_duration: Duration::from_millis(500),774 #[cfg(feature = "lookahead")]775 authoring_duration: Duration::from_millis(1500),776 overseer_handle,777 #[cfg(feature = "lookahead")]778 code_hash_provider: move |block_hash| {779 client780 .code_at(block_hash)781 .ok()782 .map(cumulus_primitives_core::relay_chain::ValidationCode)783 .map(|c| c.hash())784 },785 collator_key,786 relay_chain_slot_duration,787 #[cfg(not(feature = "lookahead"))]788 collation_request_receiver: None,789 };790791 task_manager.spawn_essential_handle().spawn(792 "aura",793 None,794 #[cfg(not(feature = "lookahead"))]795 run_aura::<_, AuraAuthorityPair, _, _, _, _, _, _, _>(params),796 #[cfg(feature = "lookahead")]797 run_aura::<_, AuraAuthorityPair, _, _, _, _, _, _, _, _, _>(params),798 );799 Ok(())800}801802fn dev_build_import_queue<RuntimeApi, ExecutorDispatch>(803 client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,804 _: Arc<FullBackend>,805 config: &Configuration,806 _: Option<TelemetryHandle>,807 task_manager: &TaskManager,808) -> Result<sc_consensus::DefaultImportQueue<Block>, sc_service::Error>809where810 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>811 + Send812 + Sync813 + 'static,814 RuntimeApi::RuntimeApi:815 sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> + sp_api::ApiExt<Block>,816 ExecutorDispatch: NativeExecutionDispatch + 'static,817{818 Ok(sc_consensus_manual_seal::import_queue(819 Box::new(client),820 &task_manager.spawn_essential_handle(),821 config.prometheus_registry(),822 ))823}824825pub struct OtherPartial {826 pub telemetry: Option<Telemetry>,827 pub telemetry_worker_handle: Option<TelemetryWorkerHandle>,828 pub eth_filter_pool: Option<FilterPool>,829 pub eth_backend: Arc<fc_db::kv::Backend<Block>>,830}831832struct DefaultEthConfig<C>(PhantomData<C>);833impl<C> EthConfig<Block, C> for DefaultEthConfig<C>834where835 C: StorageProvider<Block, FullBackend> + Sync + Send + 'static,836{837 type EstimateGasAdapter = ();838 type RuntimeStorageOverride = SystemAccountId32StorageOverride<Block, C, FullBackend>;839}840841842843pub fn start_dev_node<Runtime, RuntimeApi, ExecutorDispatch>(844 config: Configuration,845 autoseal_interval: u64,846 autoseal_finalize_delay: Option<u64>,847 disable_autoseal_on_tx: bool,848) -> sc_service::error::Result<TaskManager>849where850 Runtime: RuntimeInstance + Send + Sync + 'static,851 <Runtime as RuntimeInstance>::CrossAccountId: Serialize,852 for<'de> <Runtime as RuntimeInstance>::CrossAccountId: Deserialize<'de>,853 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>854 + Send855 + Sync856 + 'static,857 RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,858 ExecutorDispatch: NativeExecutionDispatch + 'static,859{860 use fc_consensus::FrontierBlockImport;861 use sc_consensus_manual_seal::{862 run_delayed_finalize, run_manual_seal, DelayedFinalizeParams, EngineCommand,863 ManualSealParams,864 };865866 let sc_service::PartialComponents {867 client,868 backend,869 mut task_manager,870 import_queue,871 keystore_container,872 select_chain: maybe_select_chain,873 transaction_pool,874 other:875 OtherPartial {876 telemetry,877 eth_filter_pool,878 eth_backend,879 telemetry_worker_handle: _,880 },881 } = new_partial::<Runtime, RuntimeApi, ExecutorDispatch, _>(882 &config,883 dev_build_import_queue::<RuntimeApi, ExecutorDispatch>,884 )?;885 let net_config = sc_network::config::FullNetworkConfiguration::new(&config.network);886 let prometheus_registry = config.prometheus_registry().cloned();887888 let (network, system_rpc_tx, tx_handler_controller, network_starter, sync_service) =889 sc_service::build_network(sc_service::BuildNetworkParams {890 config: &config,891 net_config,892 client: client.clone(),893 transaction_pool: transaction_pool.clone(),894 spawn_handle: task_manager.spawn_handle(),895 import_queue,896 block_announce_validator_builder: None,897 warp_sync_params: None,898 block_relay: None,899 })?;900901 let collator = config.role.is_authority();902903 let select_chain = maybe_select_chain;904905 if collator {906 let block_import = FrontierBlockImport::new(client.clone(), client.clone());907908 let env = sc_basic_authorship::ProposerFactory::new(909 task_manager.spawn_handle(),910 client.clone(),911 transaction_pool.clone(),912 prometheus_registry.as_ref(),913 telemetry.as_ref().map(|x| x.handle()),914 );915916 let transactions_commands_stream: Box<917 dyn Stream<Item = EngineCommand<Hash>> + Send + Sync + Unpin,918 > = Box::new(919 transaction_pool920 .pool()921 .validated_pool()922 .import_notification_stream()923 .filter(move |_| futures::future::ready(!disable_autoseal_on_tx))924 .map(|_| EngineCommand::SealNewBlock {925 create_empty: true,926 finalize: false,927 parent_hash: None,928 sender: None,929 }),930 );931932 let autoseal_interval = Box::pin(AutosealInterval::new(&config, autoseal_interval));933934 let idle_commands_stream: Box<935 dyn Stream<Item = EngineCommand<Hash>> + Send + Sync + Unpin,936 > = Box::new(autoseal_interval.map(|_| EngineCommand::SealNewBlock {937 create_empty: true,938 finalize: false,939 parent_hash: None,940 sender: None,941 }));942943 let commands_stream = select(transactions_commands_stream, idle_commands_stream);944945 let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;946 let client_set_aside_for_cidp = client.clone();947948 if let Some(delay_sec) = autoseal_finalize_delay {949 let spawn_handle = task_manager.spawn_handle();950951 task_manager.spawn_essential_handle().spawn_blocking(952 "finalization_task",953 Some("block-authoring"),954 run_delayed_finalize(DelayedFinalizeParams {955 client: client.clone(),956 delay_sec,957 spawn_handle,958 }),959 );960 }961962 task_manager.spawn_essential_handle().spawn_blocking(963 "authorship_task",964 Some("block-authoring"),965 run_manual_seal(ManualSealParams {966 block_import,967 env,968 client: client.clone(),969 pool: transaction_pool.clone(),970 commands_stream,971 select_chain: select_chain.clone(),972 consensus_data_provider: None,973 create_inherent_data_providers: move |block: Hash, ()| {974 let current_para_block = client_set_aside_for_cidp975 .number(block)976 .expect("Header lookup should succeed")977 .expect("Header passed in as parent should be present in backend.");978979 let client_for_xcm = client_set_aside_for_cidp.clone();980 async move {981 let time = sp_timestamp::InherentDataProvider::from_system_time();982983 let mocked_parachain = cumulus_client_parachain_inherent::MockValidationDataInherentDataProvider {984 current_para_block,985 relay_offset: 1000,986 relay_blocks_per_para_block: 2,987 para_blocks_per_relay_epoch: 0,988 xcm_config: cumulus_client_parachain_inherent::MockXcmConfig::new(989 &*client_for_xcm,990 block,991 Default::default(),992 Default::default(),993 ),994 relay_randomness_config: (),995 raw_downward_messages: vec![],996 raw_horizontal_messages: vec![],997 additional_key_values: None,998 };9991000 let slot =1001 sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(1002 *time,1003 slot_duration,1004 );10051006 Ok((time, slot, mocked_parachain))1007 }1008 },1009 }),1010 );1011 }10121013 #[cfg(feature = "pov-estimate")]1014 let rpc_backend = backend.clone();10151016 let runtime_id = config.chain_spec.runtime_id();10171018 1019 let fee_history_cache: FeeHistoryCache = Arc::new(Mutex::new(BTreeMap::new()));1020 let fee_history_limit = 2048;10211022 let eth_pubsub_notification_sinks: Arc<1023 EthereumBlockNotificationSinks<fc_mapping_sync::EthereumBlockNotification<Block>>,1024 > = Default::default();10251026 let overrides = overrides_handle(client.clone());1027 let eth_block_data_cache = spawn_frontier_tasks(1028 FrontierTaskParams {1029 client: client.clone(),1030 substrate_backend: backend.clone(),1031 eth_filter_pool: eth_filter_pool.clone(),1032 eth_backend: eth_backend.clone(),1033 fee_history_limit,1034 fee_history_cache: fee_history_cache.clone(),1035 task_manager: &task_manager,1036 prometheus_registry,1037 overrides: overrides.clone(),1038 sync_strategy: SyncStrategy::Normal,1039 },1040 sync_service.clone(),1041 eth_pubsub_notification_sinks.clone(),1042 );10431044 1045 let rpc_builder = Box::new({1046 clone!(1047 client,1048 backend,1049 eth_backend,1050 eth_pubsub_notification_sinks,1051 fee_history_cache,1052 eth_block_data_cache,1053 overrides,1054 transaction_pool,1055 network,1056 sync_service,1057 );1058 move |deny_unsafe, subscription_task_executor: SubscriptionTaskExecutor| {1059 clone!(1060 backend,1061 eth_block_data_cache,1062 client,1063 eth_backend,1064 eth_filter_pool,1065 eth_pubsub_notification_sinks,1066 fee_history_cache,1067 eth_block_data_cache,1068 network,1069 runtime_id,1070 transaction_pool,1071 select_chain,1072 overrides,1073 );10741075 #[cfg(not(feature = "pov-estimate"))]1076 let _ = backend;10771078 let mut rpc_module = RpcModule::new(());10791080 let full_deps = FullDeps {1081 runtime_id,10821083 #[cfg(feature = "pov-estimate")]1084 exec_params: uc_rpc::pov_estimate::ExecutorParams {1085 wasm_method: config.wasm_method,1086 default_heap_pages: config.default_heap_pages,1087 max_runtime_instances: config.max_runtime_instances,1088 runtime_cache_size: config.runtime_cache_size,1089 },10901091 #[cfg(feature = "pov-estimate")]1092 backend,1093 1094 deny_unsafe,1095 client: client.clone(),1096 pool: transaction_pool.clone(),1097 select_chain,1098 };10991100 create_full::<_, _, _, Runtime, _>(&mut rpc_module, full_deps)?;11011102 let eth_deps = EthDeps {1103 client,1104 graph: transaction_pool.pool().clone(),1105 pool: transaction_pool,1106 is_authority: true,1107 network,1108 eth_backend,1109 1110 max_past_logs: 10000,1111 fee_history_limit,1112 fee_history_cache,1113 eth_block_data_cache,1114 1115 enable_dev_signer: false,1116 eth_filter_pool,1117 eth_pubsub_notification_sinks,1118 overrides,1119 sync: sync_service.clone(),1120 1121 pending_create_inherent_data_providers: |_, ()| async move { Ok(()) },1122 };11231124 create_eth::<1125 _,1126 _,1127 _,1128 _,1129 _,1130 _,1131 DefaultEthConfig<FullClient<RuntimeApi, ExecutorDispatch>>,1132 >(1133 &mut rpc_module,1134 eth_deps,1135 subscription_task_executor.clone(),1136 )?;11371138 Ok(rpc_module)1139 }1140 });11411142 sc_service::spawn_tasks(sc_service::SpawnTasksParams {1143 network,1144 sync_service,1145 client,1146 keystore: keystore_container.keystore(),1147 task_manager: &mut task_manager,1148 transaction_pool,1149 rpc_builder,1150 backend,1151 system_rpc_tx,1152 config,1153 telemetry: None,1154 tx_handler_controller,1155 })?;11561157 network_starter.start_network();1158 Ok(task_manager)1159}11601161fn overrides_handle<C, BE>(client: Arc<C>) -> Arc<OverrideHandle<Block>>1162where1163 C: ProvideRuntimeApi<Block> + StorageProvider<Block, BE> + AuxStore,1164 C: HeaderBackend<Block> + HeaderMetadata<Block, Error = BlockChainError>,1165 C: Send + Sync + 'static,1166 C::Api: fp_rpc::EthereumRuntimeRPCApi<Block>,1167 BE: Backend<Block> + 'static,1168 BE::State: StateBackend<BlakeTwo256>,1169{1170 let mut overrides_map = BTreeMap::new();1171 overrides_map.insert(1172 EthereumStorageSchema::V1,1173 Box::new(SchemaV1Override::new(client.clone())) as Box<dyn StorageOverride<_> + 'static>,1174 );1175 overrides_map.insert(1176 EthereumStorageSchema::V2,1177 Box::new(SchemaV2Override::new(client.clone())) as Box<dyn StorageOverride<_> + 'static>,1178 );1179 overrides_map.insert(1180 EthereumStorageSchema::V3,1181 Box::new(SchemaV3Override::new(client.clone())) as Box<dyn StorageOverride<_> + 'static>,1182 );11831184 Arc::new(OverrideHandle {1185 schemas: overrides_map,1186 fallback: Box::new(RuntimeApiStorageOverride::new(client)),1187 })1188}11891190pub struct FrontierTaskParams<'a, C, B> {1191 pub task_manager: &'a TaskManager,1192 pub client: Arc<C>,1193 pub substrate_backend: Arc<B>,1194 pub eth_backend: Arc<fc_db::kv::Backend<Block>>,1195 pub eth_filter_pool: Option<FilterPool>,1196 pub overrides: Arc<OverrideHandle<Block>>,1197 pub fee_history_limit: u64,1198 pub fee_history_cache: FeeHistoryCache,1199 pub sync_strategy: SyncStrategy,1200 pub prometheus_registry: Option<Registry>,1201}12021203pub fn spawn_frontier_tasks<C, B>(1204 params: FrontierTaskParams<C, B>,1205 sync: Arc<SyncingService<Block>>,1206 pubsub_notification_sinks: Arc<1207 EthereumBlockNotificationSinks<fc_mapping_sync::EthereumBlockNotification<Block>>,1208 >,1209) -> Arc<EthBlockDataCacheTask<Block>>1210where1211 C: ProvideRuntimeApi<Block> + BlockOf,1212 C: HeaderBackend<Block> + HeaderMetadata<Block, Error = BlockChainError> + 'static,1213 C: BlockchainEvents<Block> + StorageProvider<Block, B>,1214 C: Send + Sync + 'static,1215 C::Api: EthereumRuntimeRPCApi<Block>,1216 C::Api: BlockBuilder<Block>,1217 B: Backend<Block> + 'static,1218 B::State: StateBackend<BlakeTwo256>,1219{1220 let FrontierTaskParams {1221 task_manager,1222 client,1223 substrate_backend,1224 eth_backend,1225 eth_filter_pool,1226 overrides,1227 fee_history_limit,1228 fee_history_cache,1229 sync_strategy,1230 prometheus_registry,1231 } = params;1232 1233 1234 params.task_manager.spawn_essential_handle().spawn(1235 "frontier-mapping-sync-worker",1236 Some("frontier"),1237 MappingSyncWorker::new(1238 client.import_notification_stream(),1239 Duration::new(6, 0),1240 client.clone(),1241 substrate_backend,1242 overrides.clone(),1243 eth_backend,1244 3,1245 0,1246 sync_strategy,1247 sync,1248 pubsub_notification_sinks,1249 )1250 .for_each(|()| futures::future::ready(())),1251 );12521253 1254 1255 if let Some(eth_filter_pool) = eth_filter_pool {1256 1257 const FILTER_RETAIN_THRESHOLD: u64 = 100;1258 params.task_manager.spawn_essential_handle().spawn(1259 "frontier-filter-pool",1260 Some("frontier"),1261 EthTask::filter_pool_task(client.clone(), eth_filter_pool, FILTER_RETAIN_THRESHOLD),1262 );1263 }12641265 1266 params.task_manager.spawn_essential_handle().spawn(1267 "frontier-fee-history",1268 Some("frontier"),1269 EthTask::fee_history_task(1270 client,1271 overrides.clone(),1272 fee_history_cache,1273 fee_history_limit,1274 ),1275 );12761277 Arc::new(EthBlockDataCacheTask::new(1278 task_manager.spawn_handle(),1279 overrides,1280 50,1281 50,1282 prometheus_registry,1283 ))1284}