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