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, 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 trait ClientForService<Block: BlockT>:
455 ProvideRuntimeApi<Block>
456 + HeaderMetadata<Block, Error = sp_blockchain::Error>
457 + HeaderBackend<Block>
458 + BlockBackend<Block>
459 + ProofProvider<Block>
460 + BlockchainEvents<Block>
461 + 'static
462{
463}
464
465impl<Block: BlockT, T> ClientForService<Block> for T where
466 T: ProvideRuntimeApi<Block>
467 + HeaderMetadata<Block, Error = sp_blockchain::Error>
468 + HeaderBackend<Block>
469 + BlockBackend<Block>
470 + ProofProvider<Block>
471 + BlockchainEvents<Block>
472 + 'static
473{
474}
475
476pub struct SpawnTasksParams<'a, TBl: BlockT, TCl, TExPool: ?Sized, TRpc, Backend> {
478 pub config: Configuration,
480 pub client: Arc<TCl>,
482 pub backend: Arc<Backend>,
484 pub task_manager: &'a mut TaskManager,
486 pub keystore: KeystorePtr,
488 pub transaction_pool: Arc<TExPool>,
490 pub rpc_builder: Box<dyn Fn(SubscriptionTaskExecutor) -> Result<RpcModule<TRpc>, Error>>,
492 pub network: Arc<dyn sc_network::service::traits::NetworkService>,
494 pub system_rpc_tx: TracingUnboundedSender<sc_rpc::system::Request<TBl>>,
496 pub tx_handler_controller:
498 sc_network_transactions::TransactionsHandlerController<<TBl as BlockT>::Hash>,
499 pub sync_service: Arc<SyncingService<TBl>>,
501 pub telemetry: Option<&'a mut Telemetry>,
503 pub tracing_execute_block: Option<Arc<dyn TracingExecuteBlock<TBl>>>,
507}
508
509pub fn spawn_tasks<TBl, TBackend, TExPool, TRpc, TCl>(
511 SpawnTasksParams {
512 mut config,
513 task_manager,
514 client,
515 backend,
516 keystore,
517 transaction_pool,
518 rpc_builder,
519 network,
520 system_rpc_tx,
521 tx_handler_controller,
522 sync_service,
523 telemetry,
524 tracing_execute_block: execute_block,
525 }: SpawnTasksParams<TBl, TCl, TExPool, TRpc, TBackend>,
526) -> Result<RpcHandlers, Error>
527where
528 TCl: ClientForService<TBl>
529 + Chain<TBl>
530 + ExecutorProvider<TBl>
531 + UsageProvider<TBl>
532 + StorageProvider<TBl, TBackend>
533 + CallApiAt<TBl>,
534 <TCl as ProvideRuntimeApi<TBl>>::Api:
535 sp_api::Metadata<TBl> + sp_session::SessionKeys<TBl> + sp_api::ApiExt<TBl>,
536 TBl: BlockT,
537 TBl::Hash: Unpin,
538 TBl::Header: Unpin,
539 TBackend: 'static + sc_client_api::backend::Backend<TBl> + Send,
540 TExPool:
541 MaintainedTransactionPool<Block = TBl, Hash = <TBl as BlockT>::Hash> + ?Sized + 'static,
542{
543 let chain_info = client.usage_info().chain;
544
545 sp_session::generate_initial_session_keys(
546 client.clone(),
547 chain_info.best_hash,
548 config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(),
549 keystore.clone(),
550 )
551 .map_err(|e| Error::Application(Box::new(e)))?;
552
553 let sysinfo = sc_sysinfo::gather_sysinfo();
554 sc_sysinfo::print_sysinfo(&sysinfo);
555
556 let telemetry = telemetry
557 .map(|telemetry| {
558 init_telemetry(
559 config.network.node_name.clone(),
560 config.impl_name.clone(),
561 config.impl_version.clone(),
562 config.chain_spec.name().to_string(),
563 config.role.is_authority(),
564 network.clone(),
565 client.clone(),
566 telemetry,
567 Some(sysinfo),
568 )
569 })
570 .transpose()?;
571
572 info!("📦 Highest known block at #{}", chain_info.best_number);
573
574 let spawn_handle = task_manager.spawn_handle();
575
576 spawn_handle.spawn(
578 "txpool-notifications",
579 Some("transaction-pool"),
580 sc_transaction_pool::notification_future(
581 client.clone(),
582 transaction_pool.clone(),
583 config.transaction_pool.use_all_block_notifications(),
584 ),
585 );
586
587 spawn_handle.spawn(
588 "on-transaction-imported",
589 Some("transaction-pool"),
590 propagate_transaction_notifications(
591 transaction_pool.clone(),
592 tx_handler_controller,
593 telemetry.clone(),
594 ),
595 );
596
597 let metrics_service =
599 if let Some(PrometheusConfig { port, registry }) = config.prometheus_config.clone() {
600 let metrics = MetricsService::with_prometheus(
602 telemetry,
603 ®istry,
604 config.role,
605 &config.network.node_name,
606 &config.impl_version,
607 )?;
608 spawn_handle.spawn(
609 "prometheus-endpoint",
610 None,
611 prometheus_endpoint::init_prometheus(port, registry).map(drop),
612 );
613
614 metrics
615 } else {
616 MetricsService::new(telemetry)
617 };
618
619 spawn_handle.spawn(
621 "telemetry-periodic-send",
622 None,
623 metrics_service.run(
624 client.clone(),
625 transaction_pool.clone(),
626 network.clone(),
627 sync_service.clone(),
628 ),
629 );
630
631 let rpc_id_provider = config.rpc.id_provider.take();
632
633 let rpc_v2_metrics = config
638 .prometheus_registry()
639 .map(|registry| sc_rpc_spec_v2::transaction::TransactionMetrics::new(registry))
640 .transpose()?;
641
642 let rpc_runtime = sc_rpc_server::create_rpc_runtime(config.rpc.max_connections)
645 .map_err(|e| Error::Application(Box::new(e)))?;
646
647 let rpc_spawn_handle: Arc<dyn sp_core::traits::SpawnNamed> =
649 Arc::new(sc_rpc_server::RpcSpawnHandle::new(rpc_runtime.handle().clone()));
650
651 let gen_rpc_module = || {
653 gen_rpc_module(GenRpcModuleParams {
654 spawn_handle: rpc_spawn_handle.clone(),
655 client: client.clone(),
656 transaction_pool: transaction_pool.clone(),
657 keystore: keystore.clone(),
658 system_rpc_tx: system_rpc_tx.clone(),
659 impl_name: config.impl_name.clone(),
660 impl_version: config.impl_version.clone(),
661 chain_spec: config.chain_spec.as_ref(),
662 state_pruning: &config.state_pruning,
663 blocks_pruning: config.blocks_pruning,
664 backend: backend.clone(),
665 rpc_builder: &*rpc_builder,
666 metrics: rpc_v2_metrics.clone(),
667 sync_oracle: sync_service.clone(),
668 tracing_execute_block: execute_block.clone(),
669 })
670 };
671
672 let rpc_api = gen_rpc_module()?;
674
675 let rpc_server_handle = start_rpc_servers(
676 &config.rpc,
677 config.prometheus_registry(),
678 &config.tokio_handle,
679 rpc_api,
680 rpc_runtime,
681 rpc_id_provider,
682 )?;
683
684 let listen_addrs = rpc_server_handle
685 .listen_addrs()
686 .into_iter()
687 .map(|socket_addr| {
688 let mut multiaddr: Multiaddr = socket_addr.ip().into();
689 multiaddr.push(Protocol::Tcp(socket_addr.port()));
690 multiaddr
691 })
692 .collect();
693
694 let in_memory_rpc = {
696 let mut module = gen_rpc_module()?;
697 module.extensions_mut().insert(DenyUnsafe::No);
698 module
699 };
700
701 let in_memory_rpc_handle = RpcHandlers::new(Arc::new(in_memory_rpc), listen_addrs);
702
703 spawn_handle.spawn(
705 "informant",
706 None,
707 sc_informant::build(client.clone(), network, sync_service.clone()),
708 );
709
710 task_manager.keep_alive((config.base_path, rpc_server_handle));
711
712 Ok(in_memory_rpc_handle)
713}
714
715pub async fn propagate_transaction_notifications<Block, ExPool>(
717 transaction_pool: Arc<ExPool>,
718 tx_handler_controller: sc_network_transactions::TransactionsHandlerController<
719 <Block as BlockT>::Hash,
720 >,
721 telemetry: Option<TelemetryHandle>,
722) where
723 Block: BlockT,
724 ExPool: MaintainedTransactionPool<Block = Block, Hash = <Block as BlockT>::Hash> + ?Sized,
725{
726 const TELEMETRY_INTERVAL: Duration = Duration::from_secs(1);
727
728 let mut notifications = transaction_pool.import_notification_stream().fuse();
730 let mut timer = futures_timer::Delay::new(TELEMETRY_INTERVAL).fuse();
731 let mut tx_imported = false;
732
733 loop {
734 select! {
735 notification = notifications.next() => {
736 let Some(hash) = notification else { return };
737
738 tx_handler_controller.propagate_transaction(hash);
739
740 tx_imported = true;
741 },
742 _ = timer => {
743 timer = futures_timer::Delay::new(TELEMETRY_INTERVAL).fuse();
744
745 if !tx_imported {
746 continue;
747 }
748
749 tx_imported = false;
750 let status = transaction_pool.status();
751
752 telemetry!(
753 telemetry;
754 SUBSTRATE_INFO;
755 "txpool.import";
756 "ready" => status.ready,
757 "future" => status.future,
758 );
759 }
760 }
761 }
762}
763
764pub fn init_telemetry<Block, Client, Network>(
766 name: String,
767 implementation: String,
768 version: String,
769 chain: String,
770 authority: bool,
771 network: Network,
772 client: Arc<Client>,
773 telemetry: &mut Telemetry,
774 sysinfo: Option<sc_telemetry::SysInfo>,
775) -> sc_telemetry::Result<TelemetryHandle>
776where
777 Block: BlockT,
778 Client: BlockBackend<Block>,
779 Network: NetworkStateInfo,
780{
781 let genesis_hash = client.block_hash(Zero::zero()).ok().flatten().unwrap_or_default();
782 let connection_message = ConnectionMessage {
783 name,
784 implementation,
785 version,
786 target_os: sc_sysinfo::TARGET_OS.into(),
787 target_arch: sc_sysinfo::TARGET_ARCH.into(),
788 target_env: sc_sysinfo::TARGET_ENV.into(),
789 config: String::new(),
790 chain,
791 genesis_hash: format!("{:?}", genesis_hash),
792 authority,
793 startup_time: SystemTime::UNIX_EPOCH
794 .elapsed()
795 .map(|dur| dur.as_millis())
796 .unwrap_or(0)
797 .to_string(),
798 network_id: network.local_peer_id().to_base58(),
799 sysinfo,
800 };
801
802 telemetry.start_telemetry(connection_message)?;
803
804 Ok(telemetry.handle())
805}
806
807pub struct GenRpcModuleParams<'a, TBl: BlockT, TBackend, TCl, TRpc, TExPool: ?Sized> {
809 pub spawn_handle: Arc<dyn sp_core::traits::SpawnNamed>,
811 pub client: Arc<TCl>,
813 pub transaction_pool: Arc<TExPool>,
815 pub keystore: KeystorePtr,
817 pub system_rpc_tx: TracingUnboundedSender<sc_rpc::system::Request<TBl>>,
819 pub impl_name: String,
821 pub impl_version: String,
823 pub chain_spec: &'a dyn ChainSpec,
825 pub state_pruning: &'a Option<PruningMode>,
827 pub blocks_pruning: BlocksPruning,
829 pub backend: Arc<TBackend>,
831 pub rpc_builder: &'a dyn Fn(SubscriptionTaskExecutor) -> Result<RpcModule<TRpc>, Error>,
833 pub metrics: Option<sc_rpc_spec_v2::transaction::TransactionMetrics>,
835 pub sync_oracle: Arc<dyn sp_consensus::SyncOracle + Send + Sync>,
837 pub tracing_execute_block: Option<Arc<dyn TracingExecuteBlock<TBl>>>,
841}
842
843pub fn gen_rpc_module<TBl, TBackend, TCl, TRpc, TExPool>(
845 GenRpcModuleParams {
846 spawn_handle,
847 client,
848 transaction_pool,
849 keystore,
850 system_rpc_tx,
851 impl_name,
852 impl_version,
853 chain_spec,
854 state_pruning,
855 blocks_pruning,
856 backend,
857 rpc_builder,
858 metrics,
859 sync_oracle,
860 tracing_execute_block: execute_block,
861 }: GenRpcModuleParams<TBl, TBackend, TCl, TRpc, TExPool>,
862) -> Result<RpcModule<()>, Error>
863where
864 TBl: BlockT,
865 TCl: ClientForService<TBl>
866 + ExecutorProvider<TBl>
867 + CallApiAt<TBl>
868 + StorageProvider<TBl, TBackend>,
869 TBackend: sc_client_api::backend::Backend<TBl> + 'static,
870 <TCl as ProvideRuntimeApi<TBl>>::Api: sp_session::SessionKeys<TBl> + sp_api::Metadata<TBl>,
871 TBl::Hash: Unpin,
872 TBl::Header: Unpin,
873 TExPool:
874 MaintainedTransactionPool<Block = TBl, Hash = <TBl as BlockT>::Hash> + ?Sized + 'static,
875{
876 let system_info = sc_rpc::system::SystemInfo {
877 chain_name: chain_spec.name().into(),
878 impl_name,
879 impl_version,
880 properties: chain_spec.properties(),
881 chain_type: chain_spec.chain_type(),
882 };
883
884 let mut rpc_api = RpcModule::new(());
885 let task_executor = spawn_handle;
886
887 let (chain, state, child_state) = {
888 let chain = sc_rpc::chain::new_full(client.clone(), task_executor.clone()).into_rpc();
889 let (state, child_state) =
890 sc_rpc::state::new_full(client.clone(), task_executor.clone(), execute_block);
891 let state = state.into_rpc();
892 let child_state = child_state.into_rpc();
893
894 (chain, state, child_state)
895 };
896
897 const MAX_TRANSACTION_PER_CONNECTION: usize = 16;
898
899 let transaction_broadcast_rpc_v2 = sc_rpc_spec_v2::transaction::TransactionBroadcast::new(
900 client.clone(),
901 transaction_pool.clone(),
902 task_executor.clone(),
903 MAX_TRANSACTION_PER_CONNECTION,
904 )
905 .into_rpc();
906
907 let transaction_v2 = sc_rpc_spec_v2::transaction::Transaction::new(
908 client.clone(),
909 transaction_pool.clone(),
910 task_executor.clone(),
911 metrics,
912 )
913 .into_rpc();
914
915 let chain_head_v2 = sc_rpc_spec_v2::chain_head::ChainHead::new(
916 client.clone(),
917 backend.clone(),
918 task_executor.clone(),
919 sc_rpc_spec_v2::chain_head::ChainHeadConfig::default(),
921 )
922 .into_rpc();
923
924 let is_archive_node = state_pruning.as_ref().map(|sp| sp.is_archive()).unwrap_or(false) &&
929 blocks_pruning.is_archive();
930 let genesis_hash = client.hash(Zero::zero()).ok().flatten().expect("Genesis block exists; qed");
931 if is_archive_node {
932 let archive_v2 = sc_rpc_spec_v2::archive::Archive::new(
933 client.clone(),
934 backend.clone(),
935 genesis_hash,
936 task_executor.clone(),
937 )
938 .into_rpc();
939 rpc_api.merge(archive_v2).map_err(|e| Error::Application(e.into()))?;
940 }
941
942 let chain_spec_v2 = sc_rpc_spec_v2::chain_spec::ChainSpec::new(
944 chain_spec.name().into(),
945 genesis_hash,
946 chain_spec.properties(),
947 )
948 .into_rpc();
949
950 let bitswap_v2 = sc_rpc_spec_v2::bitswap::Bitswap::new(client.clone(), sync_oracle).into_rpc();
952
953 let author = sc_rpc::author::Author::new(
954 client.clone(),
955 transaction_pool,
956 keystore,
957 task_executor.clone(),
958 )
959 .into_rpc();
960
961 let system = sc_rpc::system::System::new(system_info, system_rpc_tx).into_rpc();
962
963 if let Some(storage) = backend.offchain_storage() {
964 let offchain = sc_rpc::offchain::Offchain::new(storage).into_rpc();
965
966 rpc_api.merge(offchain).map_err(|e| Error::Application(e.into()))?;
967 }
968
969 rpc_api.merge(transaction_v2).map_err(|e| Error::Application(e.into()))?;
971 rpc_api
972 .merge(transaction_broadcast_rpc_v2)
973 .map_err(|e| Error::Application(e.into()))?;
974 rpc_api.merge(chain_head_v2).map_err(|e| Error::Application(e.into()))?;
975 rpc_api.merge(chain_spec_v2).map_err(|e| Error::Application(e.into()))?;
976 rpc_api.merge(bitswap_v2).map_err(|e| Error::Application(e.into()))?;
977
978 rpc_api.merge(chain).map_err(|e| Error::Application(e.into()))?;
980 rpc_api.merge(author).map_err(|e| Error::Application(e.into()))?;
981 rpc_api.merge(system).map_err(|e| Error::Application(e.into()))?;
982 rpc_api.merge(state).map_err(|e| Error::Application(e.into()))?;
983 rpc_api.merge(child_state).map_err(|e| Error::Application(e.into()))?;
984 let extra_rpcs = rpc_builder(task_executor.clone())?;
986 rpc_api.merge(extra_rpcs).map_err(|e| Error::Application(e.into()))?;
987
988 Ok(rpc_api)
989}
990
991pub struct BuildNetworkParams<'a, Block, Net, TxPool: ?Sized, IQ, Client>
993where
994 Block: BlockT,
995 Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
996{
997 pub config: &'a Configuration,
999 pub net_config: FullNetworkConfiguration<Block, <Block as BlockT>::Hash, Net>,
1001 pub client: Arc<Client>,
1003 pub transaction_pool: Arc<TxPool>,
1005 pub spawn_handle: SpawnTaskHandle,
1007 pub spawn_essential_handle: SpawnEssentialTaskHandle,
1009 pub import_queue: IQ,
1011 pub block_announce_validator_builder: Option<
1013 Box<dyn FnOnce(Arc<Client>) -> Box<dyn BlockAnnounceValidator<Block> + Send> + Send>,
1014 >,
1015 pub warp_sync_config: Option<WarpSyncConfig<Block>>,
1017 pub block_relay: Option<BlockRelayParams<Block, Net>>,
1020 pub metrics: NotificationMetrics,
1022 pub gap_sync_body_policy: Option<GapSyncBodyPolicyProvider>,
1026}
1027
1028pub fn build_network<Block, Net, TxPool, IQ, Client>(
1030 params: BuildNetworkParams<Block, Net, TxPool, IQ, Client>,
1031) -> Result<
1032 (
1033 Arc<dyn sc_network::service::traits::NetworkService>,
1034 TracingUnboundedSender<sc_rpc::system::Request<Block>>,
1035 sc_network_transactions::TransactionsHandlerController<<Block as BlockT>::Hash>,
1036 Arc<SyncingService<Block>>,
1037 Option<sc_network_bitswap::BitswapHandle>,
1038 ),
1039 Error,
1040>
1041where
1042 Block: BlockT,
1043 Client: ClientForService<Block> + Chain<Block>,
1044 TxPool: TransactionPool<Block = Block, Hash = <Block as BlockT>::Hash> + ?Sized + 'static,
1045 IQ: ImportQueue<Block> + 'static,
1046 Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1047{
1048 let BuildNetworkParams {
1049 config,
1050 mut net_config,
1051 client,
1052 transaction_pool,
1053 spawn_handle,
1054 spawn_essential_handle,
1055 import_queue,
1056 block_announce_validator_builder,
1057 warp_sync_config,
1058 block_relay,
1059 metrics,
1060 gap_sync_body_policy,
1061 } = params;
1062
1063 let block_announce_validator = if let Some(f) = block_announce_validator_builder {
1064 f(client.clone())
1065 } else {
1066 Box::new(DefaultBlockAnnounceValidator)
1067 };
1068
1069 let network_service_provider = NetworkServiceProvider::new();
1070 let protocol_id = config.protocol_id();
1071 let fork_id = config.chain_spec.fork_id();
1072 let metrics_registry = config.prometheus_config.as_ref().map(|config| &config.registry);
1073
1074 let block_downloader = match block_relay {
1075 Some(params) => {
1076 let BlockRelayParams { mut server, downloader, request_response_config } = params;
1077
1078 net_config.add_request_response_protocol(request_response_config);
1079
1080 spawn_handle.spawn("block-request-handler", Some("networking"), async move {
1081 server.run().await;
1082 });
1083
1084 downloader
1085 },
1086 None => build_default_block_downloader(
1087 &protocol_id,
1088 fork_id,
1089 &mut net_config,
1090 network_service_provider.handle(),
1091 Arc::clone(&client),
1092 config.network.default_peers_set.in_peers as usize +
1093 config.network.default_peers_set.out_peers as usize,
1094 &spawn_handle,
1095 ),
1096 };
1097
1098 let gap_sync_body_policy =
1099 gap_sync_body_policy.unwrap_or_else(|| default_gap_sync_body_policy(config.blocks_pruning));
1100 let syncing_strategy = build_polkadot_syncing_strategy(
1101 protocol_id.clone(),
1102 fork_id,
1103 &mut net_config,
1104 warp_sync_config,
1105 block_downloader,
1106 client.clone(),
1107 &spawn_handle,
1108 metrics_registry,
1109 gap_sync_body_policy,
1110 )?;
1111
1112 let (syncing_engine, sync_service, block_announce_config) = SyncingEngine::new(
1113 Roles::from(&config.role),
1114 Arc::clone(&client),
1115 metrics_registry,
1116 metrics.clone(),
1117 &net_config,
1118 protocol_id.clone(),
1119 fork_id,
1120 block_announce_validator,
1121 syncing_strategy,
1122 network_service_provider.handle(),
1123 import_queue.service(),
1124 net_config.peer_store_handle(),
1125 )?;
1126
1127 spawn_essential_handle.spawn_blocking("syncing", None, syncing_engine.run());
1130
1131 build_network_advanced(BuildNetworkAdvancedParams {
1132 role: config.role,
1133 protocol_id,
1134 fork_id,
1135 announce_block: config.announce_block,
1136 net_config,
1137 client,
1138 transaction_pool,
1139 spawn_handle,
1140 spawn_essential_handle,
1141 import_queue,
1142 sync_service,
1143 block_announce_config,
1144 network_service_provider,
1145 metrics_registry,
1146 metrics,
1147 blocks_pruning: config.blocks_pruning,
1148 })
1149}
1150
1151pub struct BuildNetworkAdvancedParams<'a, Block, Net, TxPool: ?Sized, IQ, Client>
1153where
1154 Block: BlockT,
1155 Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1156{
1157 pub role: Role,
1159 pub protocol_id: ProtocolId,
1161 pub fork_id: Option<&'a str>,
1163 pub announce_block: bool,
1165 pub net_config: FullNetworkConfiguration<Block, <Block as BlockT>::Hash, Net>,
1167 pub client: Arc<Client>,
1169 pub transaction_pool: Arc<TxPool>,
1171 pub spawn_handle: SpawnTaskHandle,
1173 pub spawn_essential_handle: SpawnEssentialTaskHandle,
1175 pub import_queue: IQ,
1177 pub sync_service: SyncingService<Block>,
1179 pub block_announce_config: Net::NotificationProtocolConfig,
1181 pub network_service_provider: NetworkServiceProvider,
1183 pub metrics_registry: Option<&'a Registry>,
1185 pub metrics: NotificationMetrics,
1187 pub blocks_pruning: BlocksPruning,
1189}
1190
1191pub fn build_network_advanced<Block, Net, TxPool, IQ, Client>(
1195 params: BuildNetworkAdvancedParams<Block, Net, TxPool, IQ, Client>,
1196) -> Result<
1197 (
1198 Arc<dyn sc_network::service::traits::NetworkService>,
1199 TracingUnboundedSender<sc_rpc::system::Request<Block>>,
1200 sc_network_transactions::TransactionsHandlerController<<Block as BlockT>::Hash>,
1201 Arc<SyncingService<Block>>,
1202 Option<sc_network_bitswap::BitswapHandle>,
1203 ),
1204 Error,
1205>
1206where
1207 Block: BlockT,
1208 Client: ClientForService<Block> + Chain<Block>,
1209 TxPool: TransactionPool<Block = Block, Hash = <Block as BlockT>::Hash> + ?Sized + 'static,
1210 IQ: ImportQueue<Block> + 'static,
1211 Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1212{
1213 let BuildNetworkAdvancedParams {
1214 role,
1215 protocol_id,
1216 fork_id,
1217 announce_block,
1218 mut net_config,
1219 client,
1220 transaction_pool,
1221 spawn_handle,
1222 spawn_essential_handle,
1223 import_queue,
1224 sync_service,
1225 block_announce_config,
1226 network_service_provider,
1227 metrics_registry,
1228 metrics,
1229 blocks_pruning,
1230 } = params;
1231
1232 let genesis_hash = client.info().genesis_hash;
1233 let sync_service = Arc::new(sync_service);
1234
1235 let light_client_request_protocol_config = {
1236 let (handler, protocol_config) =
1238 LightClientRequestHandler::new::<Net>(&protocol_id, fork_id, client.clone());
1239 spawn_handle.spawn("light-client-request-handler", Some("networking"), handler.run());
1240 protocol_config
1241 };
1242
1243 net_config.add_request_response_protocol(light_client_request_protocol_config);
1245
1246 let (ipfs_config, bitswap) = if net_config.network_config.ipfs_server {
1247 if !Net::SUPPORTS_IPFS {
1248 return Err(Error::Other(
1249 "the selected network backend does not support Bitswap; \
1250 set --network-backend litep2p or disable --ipfs-server"
1251 .into(),
1252 ));
1253 }
1254
1255 let ipfs_num_blocks = match blocks_pruning {
1256 BlocksPruning::KeepAll | BlocksPruning::KeepFinalized => IPFS_MAX_BLOCKS,
1257 BlocksPruning::Some(num) => std::cmp::min(num, IPFS_MAX_BLOCKS),
1258 };
1259
1260 let (ipfs_config, litep2p_bitswap_handle) = IpfsConfig::new(
1261 Box::new(IpfsIndexedTransactions::new(client.clone(), ipfs_num_blocks)),
1262 net_config.network_config.ipfs_bootnodes.clone(),
1263 );
1264
1265 let (handler, handle) = sc_network_bitswap::start::<Block, _>(
1266 client.clone(),
1267 &*sync_service,
1268 litep2p_bitswap_handle,
1269 metrics_registry,
1270 );
1271
1272 (Some(ipfs_config), Some((handler, handle)))
1273 } else {
1274 (None, None)
1275 };
1276
1277 let (transactions_handler_proto, transactions_config) =
1279 sc_network_transactions::TransactionsHandlerPrototype::new::<_, Block, Net>(
1280 protocol_id.clone(),
1281 genesis_hash,
1282 fork_id,
1283 metrics.clone(),
1284 net_config.peer_store_handle(),
1285 );
1286 net_config.add_notification_protocol(transactions_config);
1287
1288 let peer_store = net_config.take_peer_store();
1290 spawn_handle.spawn("peer-store", Some("networking"), peer_store.run());
1291
1292 let network_params = sc_network::config::Params::<Block, <Block as BlockT>::Hash, Net> {
1293 role,
1294 executor: {
1295 let spawn_handle = Clone::clone(&spawn_handle);
1296 Box::new(move |fut| {
1297 spawn_handle.spawn("libp2p-node", Some("networking"), fut);
1298 })
1299 },
1300 network_config: net_config,
1301 genesis_hash,
1302 protocol_id,
1303 fork_id: fork_id.map(ToOwned::to_owned),
1304 metrics_registry: metrics_registry.cloned(),
1305 block_announce_config,
1306 ipfs_config,
1307 notification_metrics: metrics,
1308 };
1309
1310 let has_bootnodes = !network_params.network_config.network_config.boot_nodes.is_empty();
1311 let network_mut = Net::new(network_params)?;
1312 let network = network_mut.network_service().clone();
1313
1314 let bitswap_handle = bitswap.map(|(handler, handle)| {
1317 spawn_essential_handle.spawn("bitswap-service", Some("networking"), handler);
1318 handle
1319 });
1320
1321 let (tx_handler, tx_handler_controller) = transactions_handler_proto.build(
1322 network.clone(),
1323 sync_service.clone(),
1324 Arc::new(TransactionPoolAdapter { pool: transaction_pool, client: client.clone() }),
1325 metrics_registry,
1326 )?;
1327 spawn_handle.spawn_blocking(
1328 "network-transactions-handler",
1329 Some("networking"),
1330 tx_handler.run(),
1331 );
1332
1333 spawn_handle.spawn_blocking(
1334 "chain-sync-network-service-provider",
1335 Some("networking"),
1336 network_service_provider.run(Arc::new(network.clone())),
1337 );
1338 spawn_handle.spawn("import-queue", None, {
1339 let sync_service = sync_service.clone();
1340
1341 async move { import_queue.run(sync_service.as_ref()).await }
1342 });
1343
1344 let (system_rpc_tx, system_rpc_rx) = tracing_unbounded("mpsc_system_rpc", 10_000);
1345 spawn_handle.spawn(
1346 "system-rpc-handler",
1347 Some("networking"),
1348 build_system_rpc_future::<_, _, <Block as BlockT>::Hash>(
1349 role,
1350 network_mut.network_service(),
1351 sync_service.clone(),
1352 client.clone(),
1353 system_rpc_rx,
1354 has_bootnodes,
1355 ),
1356 );
1357
1358 let future = build_network_future::<_, _, <Block as BlockT>::Hash, _>(
1359 network_mut,
1360 client,
1361 sync_service.clone(),
1362 announce_block,
1363 );
1364
1365 spawn_essential_handle.spawn_blocking("network-worker", Some("networking"), future);
1376
1377 Ok((network, system_rpc_tx, tx_handler_controller, sync_service.clone(), bitswap_handle))
1378}
1379
1380pub struct DefaultSyncingEngineConfig<'a, Block, Client, Net>
1382where
1383 Block: BlockT,
1384 Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1385{
1386 pub role: Role,
1388 pub protocol_id: ProtocolId,
1390 pub fork_id: Option<&'a str>,
1392 pub net_config: &'a mut FullNetworkConfiguration<Block, <Block as BlockT>::Hash, Net>,
1394 pub block_announce_validator: Box<dyn BlockAnnounceValidator<Block> + Send>,
1396 pub network_service_handle: NetworkServiceHandle,
1398 pub warp_sync_config: Option<WarpSyncConfig<Block>>,
1400 pub client: Arc<Client>,
1402 pub import_queue_service: Box<dyn ImportQueueService<Block>>,
1404 pub num_peers_hint: usize,
1406 pub spawn_handle: &'a SpawnTaskHandle,
1408 pub spawn_essential_handle: &'a SpawnEssentialTaskHandle,
1410 pub metrics_registry: Option<&'a Registry>,
1412 pub metrics: NotificationMetrics,
1414 pub gap_sync_body_policy: GapSyncBodyPolicyProvider,
1418}
1419
1420pub fn build_default_syncing_engine<Block, Client, Net>(
1423 config: DefaultSyncingEngineConfig<Block, Client, Net>,
1424) -> Result<(SyncingService<Block>, Net::NotificationProtocolConfig), Error>
1425where
1426 Block: BlockT,
1427 Client: HeaderBackend<Block>
1428 + BlockBackend<Block>
1429 + HeaderMetadata<Block, Error = sp_blockchain::Error>
1430 + ProofProvider<Block>
1431 + Send
1432 + Sync
1433 + 'static,
1434 Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1435{
1436 let DefaultSyncingEngineConfig {
1437 role,
1438 protocol_id,
1439 fork_id,
1440 net_config,
1441 block_announce_validator,
1442 network_service_handle,
1443 warp_sync_config,
1444 client,
1445 import_queue_service,
1446 num_peers_hint,
1447 spawn_handle,
1448 spawn_essential_handle,
1449 metrics_registry,
1450 metrics,
1451 gap_sync_body_policy,
1452 } = config;
1453
1454 let block_downloader = build_default_block_downloader(
1455 &protocol_id,
1456 fork_id,
1457 net_config,
1458 network_service_handle.clone(),
1459 client.clone(),
1460 num_peers_hint,
1461 spawn_handle,
1462 );
1463 let syncing_strategy = build_polkadot_syncing_strategy(
1464 protocol_id.clone(),
1465 fork_id,
1466 net_config,
1467 warp_sync_config,
1468 block_downloader,
1469 client.clone(),
1470 spawn_handle,
1471 metrics_registry,
1472 gap_sync_body_policy,
1473 )?;
1474
1475 let (syncing_engine, sync_service, block_announce_config) = SyncingEngine::new(
1476 Roles::from(&role),
1477 client,
1478 metrics_registry,
1479 metrics,
1480 &net_config,
1481 protocol_id,
1482 fork_id,
1483 block_announce_validator,
1484 syncing_strategy,
1485 network_service_handle,
1486 import_queue_service,
1487 net_config.peer_store_handle(),
1488 )?;
1489
1490 spawn_essential_handle.spawn_blocking("syncing", None, syncing_engine.run());
1493
1494 Ok((sync_service, block_announce_config))
1495}
1496
1497pub fn build_default_block_downloader<Block, Client, Net>(
1499 protocol_id: &ProtocolId,
1500 fork_id: Option<&str>,
1501 net_config: &mut FullNetworkConfiguration<Block, <Block as BlockT>::Hash, Net>,
1502 network_service_handle: NetworkServiceHandle,
1503 client: Arc<Client>,
1504 num_peers_hint: usize,
1505 spawn_handle: &SpawnTaskHandle,
1506) -> Arc<dyn BlockDownloader<Block>>
1507where
1508 Block: BlockT,
1509 Client: HeaderBackend<Block> + BlockBackend<Block> + Send + Sync + 'static,
1510 Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1511{
1512 let BlockRelayParams { mut server, downloader, request_response_config } =
1515 BlockRequestHandler::new::<Net>(
1516 network_service_handle,
1517 &protocol_id,
1518 fork_id,
1519 client.clone(),
1520 num_peers_hint,
1521 );
1522
1523 spawn_handle.spawn("block-request-handler", Some("networking"), async move {
1524 server.run().await;
1525 });
1526
1527 net_config.add_request_response_protocol(request_response_config);
1528
1529 downloader
1530}
1531
1532pub fn default_gap_sync_body_policy(blocks_pruning: BlocksPruning) -> GapSyncBodyPolicyProvider {
1539 Arc::new(move || {
1540 Ok(blocks_pruning
1541 .is_archive()
1542 .then_some(GapSyncBodyPolicy::All)
1543 .unwrap_or(GapSyncBodyPolicy::HeadersOnly))
1544 })
1545}
1546
1547pub fn build_polkadot_syncing_strategy<Block, Client, Net>(
1549 protocol_id: ProtocolId,
1550 fork_id: Option<&str>,
1551 net_config: &mut FullNetworkConfiguration<Block, <Block as BlockT>::Hash, Net>,
1552 warp_sync_config: Option<WarpSyncConfig<Block>>,
1553 block_downloader: Arc<dyn BlockDownloader<Block>>,
1554 client: Arc<Client>,
1555 spawn_handle: &SpawnTaskHandle,
1556 metrics_registry: Option<&Registry>,
1557 gap_sync_body_policy: GapSyncBodyPolicyProvider,
1558) -> Result<Box<dyn SyncingStrategy<Block>>, Error>
1559where
1560 Block: BlockT,
1561 Client: HeaderBackend<Block>
1562 + BlockBackend<Block>
1563 + HeaderMetadata<Block, Error = sp_blockchain::Error>
1564 + ProofProvider<Block>
1565 + Send
1566 + Sync
1567 + 'static,
1568 Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1569{
1570 if warp_sync_config.is_none() && net_config.network_config.sync_mode.is_warp() {
1571 return Err("Warp sync enabled, but no warp sync provider configured.".into());
1572 }
1573
1574 if client.requires_full_sync() {
1575 match net_config.network_config.sync_mode {
1576 SyncMode::LightState { .. } => {
1577 return Err("Fast sync doesn't work for archive nodes".into())
1578 },
1579 SyncMode::Warp => return Err("Warp sync doesn't work for archive nodes".into()),
1580 SyncMode::Full => {},
1581 }
1582 }
1583
1584 let genesis_hash = client.info().genesis_hash;
1585
1586 let (state_request_protocol_config, state_request_protocol_name) = {
1587 let num_peer_hint = net_config.network_config.default_peers_set_num_full as usize +
1588 net_config.network_config.default_peers_set.reserved_nodes.len();
1589 let (handler, protocol_config) =
1591 StateRequestHandler::new::<Net>(&protocol_id, fork_id, client.clone(), num_peer_hint);
1592 let config_name = protocol_config.protocol_name().clone();
1593
1594 spawn_handle.spawn("state-request-handler", Some("networking"), handler.run());
1595 (protocol_config, config_name)
1596 };
1597 net_config.add_request_response_protocol(state_request_protocol_config);
1598
1599 let (warp_sync_protocol_config, warp_sync_protocol_name) = match warp_sync_config.as_ref() {
1600 Some(WarpSyncConfig::WithProvider(warp_with_provider)) => {
1601 let (handler, protocol_config) = WarpSyncRequestHandler::new::<_, Net>(
1603 protocol_id,
1604 genesis_hash,
1605 fork_id,
1606 warp_with_provider.clone(),
1607 );
1608 let config_name = protocol_config.protocol_name().clone();
1609
1610 spawn_handle.spawn("warp-sync-request-handler", Some("networking"), handler.run());
1611 (Some(protocol_config), Some(config_name))
1612 },
1613 _ => (None, None),
1614 };
1615 if let Some(config) = warp_sync_protocol_config {
1616 net_config.add_request_response_protocol(config);
1617 }
1618
1619 let syncing_config = PolkadotSyncingStrategyConfig {
1620 mode: net_config.network_config.sync_mode,
1621 max_parallel_downloads: net_config.network_config.max_parallel_downloads,
1622 max_blocks_per_request: net_config.network_config.max_blocks_per_request,
1623 min_peers_to_start_warp_sync: net_config.network_config.min_peers_to_start_warp_sync,
1624 metrics_registry: metrics_registry.cloned(),
1625 state_request_protocol_name,
1626 block_downloader,
1627 gap_sync_body_policy,
1628 };
1629 Ok(Box::new(PolkadotSyncingStrategy::new(
1630 syncing_config,
1631 client,
1632 warp_sync_config,
1633 warp_sync_protocol_name,
1634 )?))
1635}