1use crate::{
20 build_network_future, build_system_rpc_future,
21 client::{Client, ClientConfig},
22 config::{Configuration, ExecutorConfiguration, KeystoreConfig, Multiaddr, PrometheusConfig},
23 error::Error,
24 metrics::MetricsService,
25 start_rpc_servers, BuildGenesisBlock, GenesisBlockBuilder, RpcHandlers,
26 SpawnEssentialTaskHandle, SpawnTaskHandle, TaskManager, TransactionPoolAdapter,
27};
28use futures::{select, FutureExt, StreamExt};
29use jsonrpsee::RpcModule;
30use log::{debug, error, info};
31use prometheus_endpoint::Registry;
32use sc_chain_spec::{get_extension, ChainSpec};
33use sc_client_api::{
34 execution_extensions::ExecutionExtensions, proof_provider::ProofProvider, BadBlocks,
35 BlockBackend, BlockchainEvents, ExecutorProvider, ForkBlocks, KeysIter, StorageProvider,
36 TrieCacheContext, UsageProvider,
37};
38use sc_client_db::{Backend, BlocksPruning, DatabaseSettings, PruningMode};
39use sc_consensus::import_queue::{ImportQueue, ImportQueueService};
40use sc_executor::{
41 sp_wasm_interface::HostFunctions, HeapAllocStrategy, RuntimeVersionOf, WasmExecutor,
42 DEFAULT_HEAP_ALLOC_STRATEGY,
43};
44use sc_keystore::LocalKeystore;
45use sc_network::{
46 config::{FullNetworkConfiguration, IpfsConfig, ProtocolId, SyncMode},
47 multiaddr::Protocol,
48 service::{
49 traits::{PeerStore, RequestResponseConfig},
50 NotificationMetrics,
51 },
52 IpfsIndexedTransactions, NetworkBackend, NetworkStateInfo,
53};
54use sc_network_common::role::{Role, Roles};
55use sc_network_light::light_client_requests::handler::LightClientRequestHandler;
56use sc_network_sync::{
57 block_relay_protocol::{BlockDownloader, BlockRelayParams},
58 block_request_handler::BlockRequestHandler,
59 engine::SyncingEngine,
60 service::network::{NetworkServiceHandle, NetworkServiceProvider},
61 state_request_handler::StateRequestHandler,
62 strategy::{
63 polkadot::{PolkadotSyncingStrategy, PolkadotSyncingStrategyConfig},
64 SyncingStrategy,
65 },
66 warp_request_handler::RequestHandler as WarpSyncRequestHandler,
67 SyncingService, WarpSyncConfig,
68};
69use sc_rpc::{
70 author::AuthorApiServer,
71 chain::ChainApiServer,
72 offchain::OffchainApiServer,
73 state::{ChildStateApiServer, StateApiServer},
74 system::SystemApiServer,
75 DenyUnsafe, SubscriptionTaskExecutor,
76};
77use sc_rpc_spec_v2::{
78 archive::ArchiveApiServer,
79 bitswap::BitswapApiServer,
80 chain_head::ChainHeadApiServer,
81 chain_spec::ChainSpecApiServer,
82 transaction::{TransactionApiServer, TransactionBroadcastApiServer},
83};
84use sc_telemetry::{telemetry, ConnectionMessage, Telemetry, TelemetryHandle, SUBSTRATE_INFO};
85use sc_tracing::block::TracingExecuteBlock;
86use sc_transaction_pool_api::{MaintainedTransactionPool, TransactionPool};
87use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedSender};
88use sp_api::{CallApiAt, ProvideRuntimeApi};
89use sp_blockchain::{HeaderBackend, HeaderMetadata};
90use sp_consensus::block_validation::{
91 BlockAnnounceValidator, Chain, DefaultBlockAnnounceValidator,
92};
93use sp_core::traits::{CodeExecutor, SpawnNamed};
94use sp_keystore::KeystorePtr;
95use sp_runtime::traits::{Block as BlockT, BlockIdTo, NumberFor, Zero};
96use sp_storage::{ChildInfo, ChildType, PrefixedStorageKey};
97use std::{
98 str::FromStr,
99 sync::Arc,
100 time::{Duration, SystemTime},
101};
102
103const IPFS_MAX_BLOCKS: u32 = 201600;
106
107pub type TFullClient<TBl, TRtApi, TExec> =
109 Client<TFullBackend<TBl>, TFullCallExecutor<TBl, TExec>, TBl, TRtApi>;
110
111pub type TFullBackend<TBl> = Backend<TBl>;
113
114pub type TFullCallExecutor<TBl, TExec> = crate::client::LocalCallExecutor<TBl, Backend<TBl>, TExec>;
116
117type TFullParts<TBl, TRtApi, TExec> =
118 (TFullClient<TBl, TRtApi, TExec>, Arc<TFullBackend<TBl>>, KeystoreContainer, TaskManager);
119
120pub struct KeystoreContainer(Arc<LocalKeystore>);
122
123impl KeystoreContainer {
124 pub fn new(config: &KeystoreConfig) -> Result<Self, Error> {
126 let keystore = Arc::new(match config {
127 KeystoreConfig::Path { path, password } => {
128 LocalKeystore::open(path.clone(), password.clone())?
129 },
130 KeystoreConfig::InMemory => LocalKeystore::in_memory(),
131 });
132
133 Ok(Self(keystore))
134 }
135
136 pub fn keystore(&self) -> KeystorePtr {
138 self.0.clone()
139 }
140
141 pub fn local_keystore(&self) -> Arc<LocalKeystore> {
143 self.0.clone()
144 }
145}
146
147pub fn new_full_client<TBl, TRtApi, TExec>(
149 config: &Configuration,
150 telemetry: Option<TelemetryHandle>,
151 executor: TExec,
152 pruning_filters: Vec<Arc<dyn sc_client_db::PruningFilter>>,
153) -> Result<TFullClient<TBl, TRtApi, TExec>, Error>
154where
155 TBl: BlockT,
156 TExec: CodeExecutor + RuntimeVersionOf + Clone,
157{
158 new_full_parts(config, telemetry, executor, pruning_filters).map(|parts| parts.0)
159}
160
161pub fn new_full_parts_record_import<TBl, TRtApi, TExec>(
166 config: &Configuration,
167 telemetry: Option<TelemetryHandle>,
168 executor: TExec,
169 enable_import_proof_recording: bool,
170 pruning_filters: Vec<Arc<dyn sc_client_db::PruningFilter>>,
171) -> Result<TFullParts<TBl, TRtApi, TExec>, Error>
172where
173 TBl: BlockT,
174 TExec: CodeExecutor + RuntimeVersionOf + Clone,
175{
176 let mut db_config = config.db_config();
177 db_config.pruning_filters = pruning_filters;
178 let backend = new_db_backend(db_config)?;
179
180 let genesis_block_builder = GenesisBlockBuilder::new(
181 config.chain_spec.as_storage_builder(),
182 !config.no_genesis(),
183 backend.clone(),
184 executor.clone(),
185 )?;
186
187 new_full_parts_with_genesis_builder(
188 config,
189 telemetry,
190 executor,
191 backend,
192 genesis_block_builder,
193 enable_import_proof_recording,
194 )
195}
196
197pub fn new_full_parts<TBl, TRtApi, TExec>(
202 config: &Configuration,
203 telemetry: Option<TelemetryHandle>,
204 executor: TExec,
205 pruning_filters: Vec<Arc<dyn sc_client_db::PruningFilter>>,
206) -> Result<TFullParts<TBl, TRtApi, TExec>, Error>
207where
208 TBl: BlockT,
209 TExec: CodeExecutor + RuntimeVersionOf + Clone,
210{
211 new_full_parts_record_import(config, telemetry, executor, false, pruning_filters)
212}
213
214pub fn new_full_parts_with_genesis_builder<TBl, TRtApi, TExec, TBuildGenesisBlock>(
216 config: &Configuration,
217 telemetry: Option<TelemetryHandle>,
218 executor: TExec,
219 backend: Arc<TFullBackend<TBl>>,
220 genesis_block_builder: TBuildGenesisBlock,
221 enable_import_proof_recording: bool,
222) -> Result<TFullParts<TBl, TRtApi, TExec>, Error>
223where
224 TBl: BlockT,
225 TExec: CodeExecutor + RuntimeVersionOf + Clone,
226 TBuildGenesisBlock: BuildGenesisBlock<
227 TBl,
228 BlockImportOperation = <Backend<TBl> as sc_client_api::backend::Backend<TBl>>::BlockImportOperation
229 >,
230{
231 let keystore_container = KeystoreContainer::new(&config.keystore)?;
232
233 let task_manager = {
234 let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry);
235 TaskManager::new(config.tokio_handle.clone(), registry)?
236 };
237
238 let chain_spec = &config.chain_spec;
239 let fork_blocks = get_extension::<ForkBlocks<TBl>>(chain_spec.extensions())
240 .cloned()
241 .unwrap_or_default();
242
243 let bad_blocks = get_extension::<BadBlocks<TBl>>(chain_spec.extensions())
244 .cloned()
245 .unwrap_or_default();
246
247 let client = {
248 let extensions = ExecutionExtensions::new(None, Arc::new(executor.clone()));
249
250 let wasm_runtime_substitutes = config
251 .chain_spec
252 .code_substitutes()
253 .into_iter()
254 .map(|(n, c)| {
255 let number = NumberFor::<TBl>::from_str(&n).map_err(|_| {
256 Error::Application(Box::from(format!(
257 "Failed to parse `{}` as block number for code substitutes. \
258 In an old version the key for code substitute was a block hash. \
259 Please update the chain spec to a version that is compatible with your node.",
260 n
261 )))
262 })?;
263 Ok((number, c))
264 })
265 .collect::<Result<std::collections::HashMap<_, _>, Error>>()?;
266
267 let client = new_client(
268 backend.clone(),
269 executor,
270 genesis_block_builder,
271 fork_blocks,
272 bad_blocks,
273 extensions,
274 Box::new(task_manager.spawn_handle()),
275 config.prometheus_config.as_ref().map(|config| config.registry.clone()),
276 telemetry,
277 ClientConfig {
278 offchain_worker_enabled: config.offchain_worker.enabled,
279 offchain_indexing_api: config.offchain_worker.indexing_enabled,
280 wasm_runtime_overrides: config.wasm_runtime_overrides.clone(),
281 no_genesis: config.no_genesis(),
282 wasm_runtime_substitutes,
283 enable_import_proof_recording,
284 },
285 )?;
286
287 if let Some(warm_up_strategy) = config.warm_up_trie_cache {
288 let storage_root = client.usage_info().chain.best_hash;
289 let backend_clone = backend.clone();
290
291 if warm_up_strategy.is_blocking() {
292 warm_up_trie_cache(backend_clone, storage_root)?;
295 } else {
296 task_manager.spawn_handle().spawn_blocking(
297 "warm-up-trie-cache",
298 None,
299 async move {
300 if let Err(e) = warm_up_trie_cache(backend_clone, storage_root) {
301 error!("Failed to warm up trie cache: {e}");
302 }
303 },
304 );
305 }
306 }
307
308 client
309 };
310
311 Ok((client, backend, keystore_container, task_manager))
312}
313
314fn child_info(key: Vec<u8>) -> Option<ChildInfo> {
315 let prefixed_key = PrefixedStorageKey::new(key);
316 ChildType::from_prefixed_key(&prefixed_key).and_then(|(child_type, storage_key)| {
317 (child_type == ChildType::ParentKeyId).then(|| ChildInfo::new_default(storage_key))
318 })
319}
320
321fn warm_up_trie_cache<TBl: BlockT>(
322 backend: Arc<TFullBackend<TBl>>,
323 storage_root: TBl::Hash,
324) -> Result<(), Error> {
325 use sc_client_api::backend::Backend;
326 use sp_state_machine::Backend as StateBackend;
327
328 let untrusted_state = || backend.state_at(storage_root, TrieCacheContext::Untrusted);
329 let trusted_state = || backend.state_at(storage_root, TrieCacheContext::Trusted);
330
331 debug!("Populating trie cache started",);
332 let start_time = std::time::Instant::now();
333 let mut keys_count = 0;
334 let mut child_keys_count = 0;
335 for key in KeysIter::<_, TBl>::new(untrusted_state()?, None, None)? {
336 if keys_count != 0 && keys_count % 100_000 == 0 {
337 debug!("{} keys and {} child keys have been warmed", keys_count, child_keys_count);
338 }
339 match child_info(key.0.clone()) {
340 Some(info) => {
341 for child_key in
342 KeysIter::<_, TBl>::new_child(untrusted_state()?, info.clone(), None, None)?
343 {
344 if trusted_state()?
345 .child_storage(&info, &child_key.0)
346 .unwrap_or_default()
347 .is_none()
348 {
349 debug!("Child storage value unexpectedly empty: {child_key:?}");
350 }
351 child_keys_count += 1;
352 }
353 },
354 None => {
355 if trusted_state()?.storage(&key.0).unwrap_or_default().is_none() {
356 debug!("Storage value unexpectedly empty: {key:?}");
357 }
358 keys_count += 1;
359 },
360 }
361 }
362 debug!(
363 "Trie cache populated with {keys_count} keys and {child_keys_count} child keys in {} s",
364 start_time.elapsed().as_secs_f32()
365 );
366
367 Ok(())
368}
369
370pub fn new_wasm_executor<H: HostFunctions>(config: &ExecutorConfiguration) -> WasmExecutor<H> {
372 let strategy = config
373 .default_heap_pages
374 .map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |p| HeapAllocStrategy::Static { extra_pages: p as _ });
375 WasmExecutor::<H>::builder()
376 .with_execution_method(config.wasm_method)
377 .with_onchain_heap_alloc_strategy(strategy)
378 .with_offchain_heap_alloc_strategy(strategy)
379 .with_max_runtime_instances(config.max_runtime_instances)
380 .with_runtime_cache_size(config.runtime_cache_size)
381 .build()
382}
383
384pub fn new_db_backend<Block>(
389 settings: DatabaseSettings,
390) -> Result<Arc<Backend<Block>>, sp_blockchain::Error>
391where
392 Block: BlockT,
393{
394 const CANONICALIZATION_DELAY: u64 = 4096;
395
396 Ok(Arc::new(Backend::new(settings, CANONICALIZATION_DELAY)?))
397}
398
399pub fn new_client<E, Block, RA, G>(
401 backend: Arc<Backend<Block>>,
402 executor: E,
403 genesis_block_builder: G,
404 fork_blocks: ForkBlocks<Block>,
405 bad_blocks: BadBlocks<Block>,
406 execution_extensions: ExecutionExtensions<Block>,
407 spawn_handle: Box<dyn SpawnNamed>,
408 prometheus_registry: Option<Registry>,
409 telemetry: Option<TelemetryHandle>,
410 config: ClientConfig<Block>,
411) -> Result<
412 Client<
413 Backend<Block>,
414 crate::client::LocalCallExecutor<Block, Backend<Block>, E>,
415 Block,
416 RA,
417 >,
418 sp_blockchain::Error,
419>
420where
421 Block: BlockT,
422 E: CodeExecutor + RuntimeVersionOf,
423 G: BuildGenesisBlock<
424 Block,
425 BlockImportOperation = <Backend<Block> as sc_client_api::backend::Backend<Block>>::BlockImportOperation
426 >,
427{
428 let executor = crate::client::LocalCallExecutor::new(
429 backend.clone(),
430 executor,
431 config.clone(),
432 execution_extensions,
433 )?;
434
435 Client::new(
436 backend,
437 executor,
438 spawn_handle,
439 genesis_block_builder,
440 fork_blocks,
441 bad_blocks,
442 prometheus_registry,
443 telemetry,
444 config,
445 )
446}
447
448pub struct SpawnTasksParams<'a, TBl: BlockT, TCl, TExPool, TRpc, Backend> {
450 pub config: Configuration,
452 pub client: Arc<TCl>,
454 pub backend: Arc<Backend>,
456 pub task_manager: &'a mut TaskManager,
458 pub keystore: KeystorePtr,
460 pub transaction_pool: Arc<TExPool>,
462 pub rpc_builder: Box<dyn Fn(SubscriptionTaskExecutor) -> Result<RpcModule<TRpc>, Error>>,
464 pub network: Arc<dyn sc_network::service::traits::NetworkService>,
466 pub system_rpc_tx: TracingUnboundedSender<sc_rpc::system::Request<TBl>>,
468 pub tx_handler_controller:
470 sc_network_transactions::TransactionsHandlerController<<TBl as BlockT>::Hash>,
471 pub sync_service: Arc<SyncingService<TBl>>,
473 pub telemetry: Option<&'a mut Telemetry>,
475 pub tracing_execute_block: Option<Arc<dyn TracingExecuteBlock<TBl>>>,
479}
480
481pub fn spawn_tasks<TBl, TBackend, TExPool, TRpc, TCl>(
483 SpawnTasksParams {
484 mut config,
485 task_manager,
486 client,
487 backend,
488 keystore,
489 transaction_pool,
490 rpc_builder,
491 network,
492 system_rpc_tx,
493 tx_handler_controller,
494 sync_service,
495 telemetry,
496 tracing_execute_block: execute_block,
497 }: SpawnTasksParams<TBl, TCl, TExPool, TRpc, TBackend>,
498) -> Result<RpcHandlers, Error>
499where
500 TCl: ProvideRuntimeApi<TBl>
501 + HeaderMetadata<TBl, Error = sp_blockchain::Error>
502 + Chain<TBl>
503 + BlockBackend<TBl>
504 + BlockIdTo<TBl, Error = sp_blockchain::Error>
505 + ProofProvider<TBl>
506 + HeaderBackend<TBl>
507 + BlockchainEvents<TBl>
508 + ExecutorProvider<TBl>
509 + UsageProvider<TBl>
510 + StorageProvider<TBl, TBackend>
511 + CallApiAt<TBl>
512 + Send
513 + 'static,
514 <TCl as ProvideRuntimeApi<TBl>>::Api: sp_api::Metadata<TBl>
515 + sp_transaction_pool::runtime_api::TaggedTransactionQueue<TBl>
516 + sp_session::SessionKeys<TBl>
517 + sp_api::ApiExt<TBl>,
518 TBl: BlockT,
519 TBl::Hash: Unpin,
520 TBl::Header: Unpin,
521 TBackend: 'static + sc_client_api::backend::Backend<TBl> + Send,
522 TExPool: MaintainedTransactionPool<Block = TBl, Hash = <TBl as BlockT>::Hash> + 'static,
523{
524 let chain_info = client.usage_info().chain;
525
526 sp_session::generate_initial_session_keys(
527 client.clone(),
528 chain_info.best_hash,
529 config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(),
530 keystore.clone(),
531 )
532 .map_err(|e| Error::Application(Box::new(e)))?;
533
534 let sysinfo = sc_sysinfo::gather_sysinfo();
535 sc_sysinfo::print_sysinfo(&sysinfo);
536
537 let telemetry = telemetry
538 .map(|telemetry| {
539 init_telemetry(
540 config.network.node_name.clone(),
541 config.impl_name.clone(),
542 config.impl_version.clone(),
543 config.chain_spec.name().to_string(),
544 config.role.is_authority(),
545 network.clone(),
546 client.clone(),
547 telemetry,
548 Some(sysinfo),
549 )
550 })
551 .transpose()?;
552
553 info!("📦 Highest known block at #{}", chain_info.best_number);
554
555 let spawn_handle = task_manager.spawn_handle();
556
557 spawn_handle.spawn(
559 "txpool-notifications",
560 Some("transaction-pool"),
561 sc_transaction_pool::notification_future(
562 client.clone(),
563 transaction_pool.clone(),
564 config.transaction_pool.use_all_block_notifications(),
565 ),
566 );
567
568 spawn_handle.spawn(
569 "on-transaction-imported",
570 Some("transaction-pool"),
571 propagate_transaction_notifications(
572 transaction_pool.clone(),
573 tx_handler_controller,
574 telemetry.clone(),
575 ),
576 );
577
578 let metrics_service =
580 if let Some(PrometheusConfig { port, registry }) = config.prometheus_config.clone() {
581 let metrics = MetricsService::with_prometheus(
583 telemetry,
584 ®istry,
585 config.role,
586 &config.network.node_name,
587 &config.impl_version,
588 )?;
589 spawn_handle.spawn(
590 "prometheus-endpoint",
591 None,
592 prometheus_endpoint::init_prometheus(port, registry).map(drop),
593 );
594
595 metrics
596 } else {
597 MetricsService::new(telemetry)
598 };
599
600 spawn_handle.spawn(
602 "telemetry-periodic-send",
603 None,
604 metrics_service.run(
605 client.clone(),
606 transaction_pool.clone(),
607 network.clone(),
608 sync_service.clone(),
609 ),
610 );
611
612 let rpc_id_provider = config.rpc.id_provider.take();
613
614 let rpc_v2_metrics = config
619 .prometheus_registry()
620 .map(|registry| sc_rpc_spec_v2::transaction::TransactionMetrics::new(registry))
621 .transpose()?;
622
623 let rpc_runtime = sc_rpc_server::create_rpc_runtime(config.rpc.max_connections)
626 .map_err(|e| Error::Application(Box::new(e)))?;
627
628 let rpc_spawn_handle: Arc<dyn sp_core::traits::SpawnNamed> =
630 Arc::new(sc_rpc_server::RpcSpawnHandle::new(rpc_runtime.handle().clone()));
631
632 let gen_rpc_module = || {
634 gen_rpc_module(GenRpcModuleParams {
635 spawn_handle: rpc_spawn_handle.clone(),
636 client: client.clone(),
637 transaction_pool: transaction_pool.clone(),
638 keystore: keystore.clone(),
639 system_rpc_tx: system_rpc_tx.clone(),
640 impl_name: config.impl_name.clone(),
641 impl_version: config.impl_version.clone(),
642 chain_spec: config.chain_spec.as_ref(),
643 state_pruning: &config.state_pruning,
644 blocks_pruning: config.blocks_pruning,
645 backend: backend.clone(),
646 rpc_builder: &*rpc_builder,
647 metrics: rpc_v2_metrics.clone(),
648 sync_oracle: sync_service.clone(),
649 tracing_execute_block: execute_block.clone(),
650 })
651 };
652
653 let rpc_api = gen_rpc_module()?;
655
656 let rpc_server_handle = start_rpc_servers(
657 &config.rpc,
658 config.prometheus_registry(),
659 &config.tokio_handle,
660 rpc_api,
661 rpc_runtime,
662 rpc_id_provider,
663 )?;
664
665 let listen_addrs = rpc_server_handle
666 .listen_addrs()
667 .into_iter()
668 .map(|socket_addr| {
669 let mut multiaddr: Multiaddr = socket_addr.ip().into();
670 multiaddr.push(Protocol::Tcp(socket_addr.port()));
671 multiaddr
672 })
673 .collect();
674
675 let in_memory_rpc = {
677 let mut module = gen_rpc_module()?;
678 module.extensions_mut().insert(DenyUnsafe::No);
679 module
680 };
681
682 let in_memory_rpc_handle = RpcHandlers::new(Arc::new(in_memory_rpc), listen_addrs);
683
684 spawn_handle.spawn(
686 "informant",
687 None,
688 sc_informant::build(client.clone(), network, sync_service.clone()),
689 );
690
691 task_manager.keep_alive((config.base_path, rpc_server_handle));
692
693 Ok(in_memory_rpc_handle)
694}
695
696pub async fn propagate_transaction_notifications<Block, ExPool>(
698 transaction_pool: Arc<ExPool>,
699 tx_handler_controller: sc_network_transactions::TransactionsHandlerController<
700 <Block as BlockT>::Hash,
701 >,
702 telemetry: Option<TelemetryHandle>,
703) where
704 Block: BlockT,
705 ExPool: MaintainedTransactionPool<Block = Block, Hash = <Block as BlockT>::Hash>,
706{
707 const TELEMETRY_INTERVAL: Duration = Duration::from_secs(1);
708
709 let mut notifications = transaction_pool.import_notification_stream().fuse();
711 let mut timer = futures_timer::Delay::new(TELEMETRY_INTERVAL).fuse();
712 let mut tx_imported = false;
713
714 loop {
715 select! {
716 notification = notifications.next() => {
717 let Some(hash) = notification else { return };
718
719 tx_handler_controller.propagate_transaction(hash);
720
721 tx_imported = true;
722 },
723 _ = timer => {
724 timer = futures_timer::Delay::new(TELEMETRY_INTERVAL).fuse();
725
726 if !tx_imported {
727 continue;
728 }
729
730 tx_imported = false;
731 let status = transaction_pool.status();
732
733 telemetry!(
734 telemetry;
735 SUBSTRATE_INFO;
736 "txpool.import";
737 "ready" => status.ready,
738 "future" => status.future,
739 );
740 }
741 }
742 }
743}
744
745pub fn init_telemetry<Block, Client, Network>(
747 name: String,
748 implementation: String,
749 version: String,
750 chain: String,
751 authority: bool,
752 network: Network,
753 client: Arc<Client>,
754 telemetry: &mut Telemetry,
755 sysinfo: Option<sc_telemetry::SysInfo>,
756) -> sc_telemetry::Result<TelemetryHandle>
757where
758 Block: BlockT,
759 Client: BlockBackend<Block>,
760 Network: NetworkStateInfo,
761{
762 let genesis_hash = client.block_hash(Zero::zero()).ok().flatten().unwrap_or_default();
763 let connection_message = ConnectionMessage {
764 name,
765 implementation,
766 version,
767 target_os: sc_sysinfo::TARGET_OS.into(),
768 target_arch: sc_sysinfo::TARGET_ARCH.into(),
769 target_env: sc_sysinfo::TARGET_ENV.into(),
770 config: String::new(),
771 chain,
772 genesis_hash: format!("{:?}", genesis_hash),
773 authority,
774 startup_time: SystemTime::UNIX_EPOCH
775 .elapsed()
776 .map(|dur| dur.as_millis())
777 .unwrap_or(0)
778 .to_string(),
779 network_id: network.local_peer_id().to_base58(),
780 sysinfo,
781 };
782
783 telemetry.start_telemetry(connection_message)?;
784
785 Ok(telemetry.handle())
786}
787
788pub struct GenRpcModuleParams<'a, TBl: BlockT, TBackend, TCl, TRpc, TExPool> {
790 pub spawn_handle: Arc<dyn sp_core::traits::SpawnNamed>,
792 pub client: Arc<TCl>,
794 pub transaction_pool: Arc<TExPool>,
796 pub keystore: KeystorePtr,
798 pub system_rpc_tx: TracingUnboundedSender<sc_rpc::system::Request<TBl>>,
800 pub impl_name: String,
802 pub impl_version: String,
804 pub chain_spec: &'a dyn ChainSpec,
806 pub state_pruning: &'a Option<PruningMode>,
808 pub blocks_pruning: BlocksPruning,
810 pub backend: Arc<TBackend>,
812 pub rpc_builder: &'a dyn Fn(SubscriptionTaskExecutor) -> Result<RpcModule<TRpc>, Error>,
814 pub metrics: Option<sc_rpc_spec_v2::transaction::TransactionMetrics>,
816 pub sync_oracle: Arc<dyn sp_consensus::SyncOracle + Send + Sync>,
818 pub tracing_execute_block: Option<Arc<dyn TracingExecuteBlock<TBl>>>,
822}
823
824pub fn gen_rpc_module<TBl, TBackend, TCl, TRpc, TExPool>(
826 GenRpcModuleParams {
827 spawn_handle,
828 client,
829 transaction_pool,
830 keystore,
831 system_rpc_tx,
832 impl_name,
833 impl_version,
834 chain_spec,
835 state_pruning,
836 blocks_pruning,
837 backend,
838 rpc_builder,
839 metrics,
840 sync_oracle,
841 tracing_execute_block: execute_block,
842 }: GenRpcModuleParams<TBl, TBackend, TCl, TRpc, TExPool>,
843) -> Result<RpcModule<()>, Error>
844where
845 TBl: BlockT,
846 TCl: ProvideRuntimeApi<TBl>
847 + BlockchainEvents<TBl>
848 + HeaderBackend<TBl>
849 + HeaderMetadata<TBl, Error = sp_blockchain::Error>
850 + ExecutorProvider<TBl>
851 + CallApiAt<TBl>
852 + ProofProvider<TBl>
853 + StorageProvider<TBl, TBackend>
854 + BlockBackend<TBl>
855 + Send
856 + Sync
857 + 'static,
858 TBackend: sc_client_api::backend::Backend<TBl> + 'static,
859 <TCl as ProvideRuntimeApi<TBl>>::Api: sp_session::SessionKeys<TBl> + sp_api::Metadata<TBl>,
860 TExPool: MaintainedTransactionPool<Block = TBl, Hash = <TBl as BlockT>::Hash> + 'static,
861 TBl::Hash: Unpin,
862 TBl::Header: Unpin,
863{
864 let system_info = sc_rpc::system::SystemInfo {
865 chain_name: chain_spec.name().into(),
866 impl_name,
867 impl_version,
868 properties: chain_spec.properties(),
869 chain_type: chain_spec.chain_type(),
870 };
871
872 let mut rpc_api = RpcModule::new(());
873 let task_executor = spawn_handle;
874
875 let (chain, state, child_state) = {
876 let chain = sc_rpc::chain::new_full(client.clone(), task_executor.clone()).into_rpc();
877 let (state, child_state) =
878 sc_rpc::state::new_full(client.clone(), task_executor.clone(), execute_block);
879 let state = state.into_rpc();
880 let child_state = child_state.into_rpc();
881
882 (chain, state, child_state)
883 };
884
885 const MAX_TRANSACTION_PER_CONNECTION: usize = 16;
886
887 let transaction_broadcast_rpc_v2 = sc_rpc_spec_v2::transaction::TransactionBroadcast::new(
888 client.clone(),
889 transaction_pool.clone(),
890 task_executor.clone(),
891 MAX_TRANSACTION_PER_CONNECTION,
892 )
893 .into_rpc();
894
895 let transaction_v2 = sc_rpc_spec_v2::transaction::Transaction::new(
896 client.clone(),
897 transaction_pool.clone(),
898 task_executor.clone(),
899 metrics,
900 )
901 .into_rpc();
902
903 let chain_head_v2 = sc_rpc_spec_v2::chain_head::ChainHead::new(
904 client.clone(),
905 backend.clone(),
906 task_executor.clone(),
907 sc_rpc_spec_v2::chain_head::ChainHeadConfig::default(),
909 )
910 .into_rpc();
911
912 let is_archive_node = state_pruning.as_ref().map(|sp| sp.is_archive()).unwrap_or(false) &&
917 blocks_pruning.is_archive();
918 let genesis_hash = client.hash(Zero::zero()).ok().flatten().expect("Genesis block exists; qed");
919 if is_archive_node {
920 let archive_v2 = sc_rpc_spec_v2::archive::Archive::new(
921 client.clone(),
922 backend.clone(),
923 genesis_hash,
924 task_executor.clone(),
925 )
926 .into_rpc();
927 rpc_api.merge(archive_v2).map_err(|e| Error::Application(e.into()))?;
928 }
929
930 let chain_spec_v2 = sc_rpc_spec_v2::chain_spec::ChainSpec::new(
932 chain_spec.name().into(),
933 genesis_hash,
934 chain_spec.properties(),
935 )
936 .into_rpc();
937
938 let bitswap_v2 = sc_rpc_spec_v2::bitswap::Bitswap::new(client.clone(), sync_oracle).into_rpc();
940
941 let author = sc_rpc::author::Author::new(
942 client.clone(),
943 transaction_pool,
944 keystore,
945 task_executor.clone(),
946 )
947 .into_rpc();
948
949 let system = sc_rpc::system::System::new(system_info, system_rpc_tx).into_rpc();
950
951 if let Some(storage) = backend.offchain_storage() {
952 let offchain = sc_rpc::offchain::Offchain::new(storage).into_rpc();
953
954 rpc_api.merge(offchain).map_err(|e| Error::Application(e.into()))?;
955 }
956
957 rpc_api.merge(transaction_v2).map_err(|e| Error::Application(e.into()))?;
959 rpc_api
960 .merge(transaction_broadcast_rpc_v2)
961 .map_err(|e| Error::Application(e.into()))?;
962 rpc_api.merge(chain_head_v2).map_err(|e| Error::Application(e.into()))?;
963 rpc_api.merge(chain_spec_v2).map_err(|e| Error::Application(e.into()))?;
964 rpc_api.merge(bitswap_v2).map_err(|e| Error::Application(e.into()))?;
965
966 rpc_api.merge(chain).map_err(|e| Error::Application(e.into()))?;
968 rpc_api.merge(author).map_err(|e| Error::Application(e.into()))?;
969 rpc_api.merge(system).map_err(|e| Error::Application(e.into()))?;
970 rpc_api.merge(state).map_err(|e| Error::Application(e.into()))?;
971 rpc_api.merge(child_state).map_err(|e| Error::Application(e.into()))?;
972 let extra_rpcs = rpc_builder(task_executor.clone())?;
974 rpc_api.merge(extra_rpcs).map_err(|e| Error::Application(e.into()))?;
975
976 Ok(rpc_api)
977}
978
979pub struct BuildNetworkParams<'a, Block, Net, TxPool, IQ, Client>
981where
982 Block: BlockT,
983 Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
984{
985 pub config: &'a Configuration,
987 pub net_config: FullNetworkConfiguration<Block, <Block as BlockT>::Hash, Net>,
989 pub client: Arc<Client>,
991 pub transaction_pool: Arc<TxPool>,
993 pub spawn_handle: SpawnTaskHandle,
995 pub spawn_essential_handle: SpawnEssentialTaskHandle,
997 pub import_queue: IQ,
999 pub block_announce_validator_builder: Option<
1001 Box<dyn FnOnce(Arc<Client>) -> Box<dyn BlockAnnounceValidator<Block> + Send> + Send>,
1002 >,
1003 pub warp_sync_config: Option<WarpSyncConfig<Block>>,
1005 pub block_relay: Option<BlockRelayParams<Block, Net>>,
1008 pub metrics: NotificationMetrics,
1010}
1011
1012pub fn build_network<Block, Net, TxPool, IQ, Client>(
1014 params: BuildNetworkParams<Block, Net, TxPool, IQ, Client>,
1015) -> Result<
1016 (
1017 Arc<dyn sc_network::service::traits::NetworkService>,
1018 TracingUnboundedSender<sc_rpc::system::Request<Block>>,
1019 sc_network_transactions::TransactionsHandlerController<<Block as BlockT>::Hash>,
1020 Arc<SyncingService<Block>>,
1021 ),
1022 Error,
1023>
1024where
1025 Block: BlockT,
1026 Client: ProvideRuntimeApi<Block>
1027 + HeaderMetadata<Block, Error = sp_blockchain::Error>
1028 + Chain<Block>
1029 + BlockBackend<Block>
1030 + BlockIdTo<Block, Error = sp_blockchain::Error>
1031 + ProofProvider<Block>
1032 + HeaderBackend<Block>
1033 + BlockchainEvents<Block>
1034 + 'static,
1035 TxPool: TransactionPool<Block = Block, Hash = <Block as BlockT>::Hash> + 'static,
1036 IQ: ImportQueue<Block> + 'static,
1037 Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1038{
1039 let BuildNetworkParams {
1040 config,
1041 mut net_config,
1042 client,
1043 transaction_pool,
1044 spawn_handle,
1045 spawn_essential_handle,
1046 import_queue,
1047 block_announce_validator_builder,
1048 warp_sync_config,
1049 block_relay,
1050 metrics,
1051 } = params;
1052
1053 let block_announce_validator = if let Some(f) = block_announce_validator_builder {
1054 f(client.clone())
1055 } else {
1056 Box::new(DefaultBlockAnnounceValidator)
1057 };
1058
1059 let network_service_provider = NetworkServiceProvider::new();
1060 let protocol_id = config.protocol_id();
1061 let fork_id = config.chain_spec.fork_id();
1062 let metrics_registry = config.prometheus_config.as_ref().map(|config| &config.registry);
1063
1064 let block_downloader = match block_relay {
1065 Some(params) => {
1066 let BlockRelayParams { mut server, downloader, request_response_config } = params;
1067
1068 net_config.add_request_response_protocol(request_response_config);
1069
1070 spawn_handle.spawn("block-request-handler", Some("networking"), async move {
1071 server.run().await;
1072 });
1073
1074 downloader
1075 },
1076 None => build_default_block_downloader(
1077 &protocol_id,
1078 fork_id,
1079 &mut net_config,
1080 network_service_provider.handle(),
1081 Arc::clone(&client),
1082 config.network.default_peers_set.in_peers as usize +
1083 config.network.default_peers_set.out_peers as usize,
1084 &spawn_handle,
1085 ),
1086 };
1087
1088 let syncing_strategy = build_polkadot_syncing_strategy(
1089 protocol_id.clone(),
1090 fork_id,
1091 &mut net_config,
1092 warp_sync_config,
1093 block_downloader,
1094 client.clone(),
1095 &spawn_handle,
1096 metrics_registry,
1097 config.blocks_pruning.is_archive(),
1098 )?;
1099
1100 let (syncing_engine, sync_service, block_announce_config) = SyncingEngine::new(
1101 Roles::from(&config.role),
1102 Arc::clone(&client),
1103 metrics_registry,
1104 metrics.clone(),
1105 &net_config,
1106 protocol_id.clone(),
1107 fork_id,
1108 block_announce_validator,
1109 syncing_strategy,
1110 network_service_provider.handle(),
1111 import_queue.service(),
1112 net_config.peer_store_handle(),
1113 )?;
1114
1115 spawn_handle.spawn_blocking("syncing", None, syncing_engine.run());
1116
1117 build_network_advanced(BuildNetworkAdvancedParams {
1118 role: config.role,
1119 protocol_id,
1120 fork_id,
1121 announce_block: config.announce_block,
1122 net_config,
1123 client,
1124 transaction_pool,
1125 spawn_handle,
1126 spawn_essential_handle,
1127 import_queue,
1128 sync_service,
1129 block_announce_config,
1130 network_service_provider,
1131 metrics_registry,
1132 metrics,
1133 blocks_pruning: config.blocks_pruning,
1134 })
1135}
1136
1137pub struct BuildNetworkAdvancedParams<'a, Block, Net, TxPool, IQ, Client>
1139where
1140 Block: BlockT,
1141 Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1142{
1143 pub role: Role,
1145 pub protocol_id: ProtocolId,
1147 pub fork_id: Option<&'a str>,
1149 pub announce_block: bool,
1151 pub net_config: FullNetworkConfiguration<Block, <Block as BlockT>::Hash, Net>,
1153 pub client: Arc<Client>,
1155 pub transaction_pool: Arc<TxPool>,
1157 pub spawn_handle: SpawnTaskHandle,
1159 pub spawn_essential_handle: SpawnEssentialTaskHandle,
1161 pub import_queue: IQ,
1163 pub sync_service: SyncingService<Block>,
1165 pub block_announce_config: Net::NotificationProtocolConfig,
1167 pub network_service_provider: NetworkServiceProvider,
1169 pub metrics_registry: Option<&'a Registry>,
1171 pub metrics: NotificationMetrics,
1173 pub blocks_pruning: BlocksPruning,
1175}
1176
1177pub fn build_network_advanced<Block, Net, TxPool, IQ, Client>(
1180 params: BuildNetworkAdvancedParams<Block, Net, TxPool, IQ, Client>,
1181) -> Result<
1182 (
1183 Arc<dyn sc_network::service::traits::NetworkService>,
1184 TracingUnboundedSender<sc_rpc::system::Request<Block>>,
1185 sc_network_transactions::TransactionsHandlerController<<Block as BlockT>::Hash>,
1186 Arc<SyncingService<Block>>,
1187 ),
1188 Error,
1189>
1190where
1191 Block: BlockT,
1192 Client: ProvideRuntimeApi<Block>
1193 + HeaderMetadata<Block, Error = sp_blockchain::Error>
1194 + Chain<Block>
1195 + BlockBackend<Block>
1196 + BlockIdTo<Block, Error = sp_blockchain::Error>
1197 + ProofProvider<Block>
1198 + HeaderBackend<Block>
1199 + BlockchainEvents<Block>
1200 + 'static,
1201 TxPool: TransactionPool<Block = Block, Hash = <Block as BlockT>::Hash> + 'static,
1202 IQ: ImportQueue<Block> + 'static,
1203 Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1204{
1205 let BuildNetworkAdvancedParams {
1206 role,
1207 protocol_id,
1208 fork_id,
1209 announce_block,
1210 mut net_config,
1211 client,
1212 transaction_pool,
1213 spawn_handle,
1214 spawn_essential_handle,
1215 import_queue,
1216 sync_service,
1217 block_announce_config,
1218 network_service_provider,
1219 metrics_registry,
1220 metrics,
1221 blocks_pruning,
1222 } = params;
1223
1224 let genesis_hash = client.info().genesis_hash;
1225
1226 let light_client_request_protocol_config = {
1227 let (handler, protocol_config) =
1229 LightClientRequestHandler::new::<Net>(&protocol_id, fork_id, client.clone());
1230 spawn_handle.spawn("light-client-request-handler", Some("networking"), handler.run());
1231 protocol_config
1232 };
1233
1234 net_config.add_request_response_protocol(light_client_request_protocol_config);
1236
1237 let ipfs_config = net_config.network_config.ipfs_server.then(|| {
1239 let (handler, bitswap_config) =
1240 Net::bitswap_server(client.clone(), metrics_registry.cloned());
1241 spawn_handle.spawn("bitswap-request-handler", Some("networking"), handler);
1242
1243 let ipfs_num_blocks = match blocks_pruning {
1244 BlocksPruning::KeepAll | BlocksPruning::KeepFinalized => IPFS_MAX_BLOCKS,
1245 BlocksPruning::Some(num) => std::cmp::min(num, IPFS_MAX_BLOCKS),
1246 };
1247
1248 IpfsConfig {
1249 bitswap_config,
1250 block_provider: Box::new(IpfsIndexedTransactions::new(client.clone(), ipfs_num_blocks)),
1251 bootnodes: net_config.network_config.ipfs_bootnodes.clone(),
1252 }
1253 });
1254
1255 let (transactions_handler_proto, transactions_config) =
1257 sc_network_transactions::TransactionsHandlerPrototype::new::<_, Block, Net>(
1258 protocol_id.clone(),
1259 genesis_hash,
1260 fork_id,
1261 metrics.clone(),
1262 net_config.peer_store_handle(),
1263 );
1264 net_config.add_notification_protocol(transactions_config);
1265
1266 let peer_store = net_config.take_peer_store();
1268 spawn_handle.spawn("peer-store", Some("networking"), peer_store.run());
1269
1270 let sync_service = Arc::new(sync_service);
1271
1272 let network_params = sc_network::config::Params::<Block, <Block as BlockT>::Hash, Net> {
1273 role,
1274 executor: {
1275 let spawn_handle = Clone::clone(&spawn_handle);
1276 Box::new(move |fut| {
1277 spawn_handle.spawn("libp2p-node", Some("networking"), fut);
1278 })
1279 },
1280 network_config: net_config,
1281 genesis_hash,
1282 protocol_id,
1283 fork_id: fork_id.map(ToOwned::to_owned),
1284 metrics_registry: metrics_registry.cloned(),
1285 block_announce_config,
1286 ipfs_config,
1287 notification_metrics: metrics,
1288 };
1289
1290 let has_bootnodes = !network_params.network_config.network_config.boot_nodes.is_empty();
1291 let network_mut = Net::new(network_params)?;
1292 let network = network_mut.network_service().clone();
1293
1294 let (tx_handler, tx_handler_controller) = transactions_handler_proto.build(
1295 network.clone(),
1296 sync_service.clone(),
1297 Arc::new(TransactionPoolAdapter { pool: transaction_pool, client: client.clone() }),
1298 metrics_registry,
1299 )?;
1300 spawn_handle.spawn_blocking(
1301 "network-transactions-handler",
1302 Some("networking"),
1303 tx_handler.run(),
1304 );
1305
1306 spawn_handle.spawn_blocking(
1307 "chain-sync-network-service-provider",
1308 Some("networking"),
1309 network_service_provider.run(Arc::new(network.clone())),
1310 );
1311 spawn_handle.spawn("import-queue", None, {
1312 let sync_service = sync_service.clone();
1313
1314 async move { import_queue.run(sync_service.as_ref()).await }
1315 });
1316
1317 let (system_rpc_tx, system_rpc_rx) = tracing_unbounded("mpsc_system_rpc", 10_000);
1318 spawn_handle.spawn(
1319 "system-rpc-handler",
1320 Some("networking"),
1321 build_system_rpc_future::<_, _, <Block as BlockT>::Hash>(
1322 role,
1323 network_mut.network_service(),
1324 sync_service.clone(),
1325 client.clone(),
1326 system_rpc_rx,
1327 has_bootnodes,
1328 ),
1329 );
1330
1331 let future = build_network_future::<_, _, <Block as BlockT>::Hash, _>(
1332 network_mut,
1333 client,
1334 sync_service.clone(),
1335 announce_block,
1336 );
1337
1338 spawn_essential_handle.spawn_blocking("network-worker", Some("networking"), future);
1349
1350 Ok((network, system_rpc_tx, tx_handler_controller, sync_service.clone()))
1351}
1352
1353pub struct DefaultSyncingEngineConfig<'a, Block, Client, Net>
1355where
1356 Block: BlockT,
1357 Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1358{
1359 pub role: Role,
1361 pub protocol_id: ProtocolId,
1363 pub fork_id: Option<&'a str>,
1365 pub net_config: &'a mut FullNetworkConfiguration<Block, <Block as BlockT>::Hash, Net>,
1367 pub block_announce_validator: Box<dyn BlockAnnounceValidator<Block> + Send>,
1369 pub network_service_handle: NetworkServiceHandle,
1371 pub warp_sync_config: Option<WarpSyncConfig<Block>>,
1373 pub client: Arc<Client>,
1375 pub import_queue_service: Box<dyn ImportQueueService<Block>>,
1377 pub num_peers_hint: usize,
1379 pub spawn_handle: &'a SpawnTaskHandle,
1381 pub metrics_registry: Option<&'a Registry>,
1383 pub metrics: NotificationMetrics,
1385 pub archive_blocks: bool,
1388}
1389
1390pub fn build_default_syncing_engine<Block, Client, Net>(
1393 config: DefaultSyncingEngineConfig<Block, Client, Net>,
1394) -> Result<(SyncingService<Block>, Net::NotificationProtocolConfig), Error>
1395where
1396 Block: BlockT,
1397 Client: HeaderBackend<Block>
1398 + BlockBackend<Block>
1399 + HeaderMetadata<Block, Error = sp_blockchain::Error>
1400 + ProofProvider<Block>
1401 + Send
1402 + Sync
1403 + 'static,
1404 Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1405{
1406 let DefaultSyncingEngineConfig {
1407 role,
1408 protocol_id,
1409 fork_id,
1410 net_config,
1411 block_announce_validator,
1412 network_service_handle,
1413 warp_sync_config,
1414 client,
1415 import_queue_service,
1416 num_peers_hint,
1417 spawn_handle,
1418 metrics_registry,
1419 metrics,
1420 archive_blocks,
1421 } = config;
1422
1423 let block_downloader = build_default_block_downloader(
1424 &protocol_id,
1425 fork_id,
1426 net_config,
1427 network_service_handle.clone(),
1428 client.clone(),
1429 num_peers_hint,
1430 spawn_handle,
1431 );
1432 let syncing_strategy = build_polkadot_syncing_strategy(
1433 protocol_id.clone(),
1434 fork_id,
1435 net_config,
1436 warp_sync_config,
1437 block_downloader,
1438 client.clone(),
1439 spawn_handle,
1440 metrics_registry,
1441 archive_blocks,
1442 )?;
1443
1444 let (syncing_engine, sync_service, block_announce_config) = SyncingEngine::new(
1445 Roles::from(&role),
1446 client,
1447 metrics_registry,
1448 metrics,
1449 &net_config,
1450 protocol_id,
1451 fork_id,
1452 block_announce_validator,
1453 syncing_strategy,
1454 network_service_handle,
1455 import_queue_service,
1456 net_config.peer_store_handle(),
1457 )?;
1458
1459 spawn_handle.spawn_blocking("syncing", None, syncing_engine.run());
1460
1461 Ok((sync_service, block_announce_config))
1462}
1463
1464pub fn build_default_block_downloader<Block, Client, Net>(
1466 protocol_id: &ProtocolId,
1467 fork_id: Option<&str>,
1468 net_config: &mut FullNetworkConfiguration<Block, <Block as BlockT>::Hash, Net>,
1469 network_service_handle: NetworkServiceHandle,
1470 client: Arc<Client>,
1471 num_peers_hint: usize,
1472 spawn_handle: &SpawnTaskHandle,
1473) -> Arc<dyn BlockDownloader<Block>>
1474where
1475 Block: BlockT,
1476 Client: HeaderBackend<Block> + BlockBackend<Block> + Send + Sync + 'static,
1477 Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1478{
1479 let BlockRelayParams { mut server, downloader, request_response_config } =
1482 BlockRequestHandler::new::<Net>(
1483 network_service_handle,
1484 &protocol_id,
1485 fork_id,
1486 client.clone(),
1487 num_peers_hint,
1488 );
1489
1490 spawn_handle.spawn("block-request-handler", Some("networking"), async move {
1491 server.run().await;
1492 });
1493
1494 net_config.add_request_response_protocol(request_response_config);
1495
1496 downloader
1497}
1498
1499pub fn build_polkadot_syncing_strategy<Block, Client, Net>(
1501 protocol_id: ProtocolId,
1502 fork_id: Option<&str>,
1503 net_config: &mut FullNetworkConfiguration<Block, <Block as BlockT>::Hash, Net>,
1504 warp_sync_config: Option<WarpSyncConfig<Block>>,
1505 block_downloader: Arc<dyn BlockDownloader<Block>>,
1506 client: Arc<Client>,
1507 spawn_handle: &SpawnTaskHandle,
1508 metrics_registry: Option<&Registry>,
1509 archive_blocks: bool,
1510) -> Result<Box<dyn SyncingStrategy<Block>>, Error>
1511where
1512 Block: BlockT,
1513 Client: HeaderBackend<Block>
1514 + BlockBackend<Block>
1515 + HeaderMetadata<Block, Error = sp_blockchain::Error>
1516 + ProofProvider<Block>
1517 + Send
1518 + Sync
1519 + 'static,
1520 Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1521{
1522 if warp_sync_config.is_none() && net_config.network_config.sync_mode.is_warp() {
1523 return Err("Warp sync enabled, but no warp sync provider configured.".into());
1524 }
1525
1526 if client.requires_full_sync() {
1527 match net_config.network_config.sync_mode {
1528 SyncMode::LightState { .. } => {
1529 return Err("Fast sync doesn't work for archive nodes".into())
1530 },
1531 SyncMode::Warp => return Err("Warp sync doesn't work for archive nodes".into()),
1532 SyncMode::Full => {},
1533 }
1534 }
1535
1536 let genesis_hash = client.info().genesis_hash;
1537
1538 let (state_request_protocol_config, state_request_protocol_name) = {
1539 let num_peer_hint = net_config.network_config.default_peers_set_num_full as usize +
1540 net_config.network_config.default_peers_set.reserved_nodes.len();
1541 let (handler, protocol_config) =
1543 StateRequestHandler::new::<Net>(&protocol_id, fork_id, client.clone(), num_peer_hint);
1544 let config_name = protocol_config.protocol_name().clone();
1545
1546 spawn_handle.spawn("state-request-handler", Some("networking"), handler.run());
1547 (protocol_config, config_name)
1548 };
1549 net_config.add_request_response_protocol(state_request_protocol_config);
1550
1551 let (warp_sync_protocol_config, warp_sync_protocol_name) = match warp_sync_config.as_ref() {
1552 Some(WarpSyncConfig::WithProvider(warp_with_provider)) => {
1553 let (handler, protocol_config) = WarpSyncRequestHandler::new::<_, Net>(
1555 protocol_id,
1556 genesis_hash,
1557 fork_id,
1558 warp_with_provider.clone(),
1559 );
1560 let config_name = protocol_config.protocol_name().clone();
1561
1562 spawn_handle.spawn("warp-sync-request-handler", Some("networking"), handler.run());
1563 (Some(protocol_config), Some(config_name))
1564 },
1565 _ => (None, None),
1566 };
1567 if let Some(config) = warp_sync_protocol_config {
1568 net_config.add_request_response_protocol(config);
1569 }
1570
1571 let syncing_config = PolkadotSyncingStrategyConfig {
1572 mode: net_config.network_config.sync_mode,
1573 max_parallel_downloads: net_config.network_config.max_parallel_downloads,
1574 max_blocks_per_request: net_config.network_config.max_blocks_per_request,
1575 min_peers_to_start_warp_sync: net_config.network_config.min_peers_to_start_warp_sync,
1576 metrics_registry: metrics_registry.cloned(),
1577 state_request_protocol_name,
1578 block_downloader,
1579 archive_blocks,
1580 };
1581 Ok(Box::new(PolkadotSyncingStrategy::new(
1582 syncing_config,
1583 client,
1584 warp_sync_config,
1585 warp_sync_protocol_name,
1586 )?))
1587}