1#![cfg(feature = "full-node")]
20
21use crate::{
22 fake_runtime_api::RuntimeApi, grandpa_support, relay_chain_selection, Error, FullBackend,
23 FullClient, IdentifyVariant, GRANDPA_JUSTIFICATION_PERIOD,
24};
25use polkadot_primitives::Block;
26use sc_consensus_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider;
27use sc_executor::{HeapAllocStrategy, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY};
28use sc_service::{Configuration, Error as SubstrateServiceError, KeystoreContainer, TaskManager};
29use sc_telemetry::{Telemetry, TelemetryWorker, TelemetryWorkerHandle};
30use sc_transaction_pool_api::OffchainTransactionPoolFactory;
31use sp_consensus::SelectChain;
32use sp_consensus_babe::inherents::BabeCreateInherentDataProviders;
33use sp_consensus_beefy::ecdsa_crypto;
34use std::sync::Arc;
35
36type FullSelectChain = relay_chain_selection::SelectRelayChain<FullBackend>;
37type FullGrandpaBlockImport<ChainSelection = FullSelectChain> =
38 sc_consensus_grandpa::GrandpaBlockImport<FullBackend, Block, FullClient, ChainSelection>;
39type FullBeefyBlockImport<InnerBlockImport, AuthorityId> =
40 sc_consensus_beefy::import::BeefyBlockImport<
41 Block,
42 FullBackend,
43 FullClient,
44 InnerBlockImport,
45 AuthorityId,
46 >;
47
48pub(crate) type PolkadotPartialComponents<ChainSelection> = sc_service::PartialComponents<
49 FullClient,
50 FullBackend,
51 ChainSelection,
52 sc_consensus::DefaultImportQueue<Block>,
53 sc_transaction_pool::TransactionPoolHandle<Block, FullClient>,
54 (
55 Box<
56 dyn Fn(
57 polkadot_rpc::SubscriptionTaskExecutor,
58 ) -> Result<polkadot_rpc::RpcExtension, SubstrateServiceError>,
59 >,
60 (
61 sc_consensus_babe::BabeBlockImport<
62 Block,
63 FullClient,
64 FullBeefyBlockImport<
65 FullGrandpaBlockImport<ChainSelection>,
66 ecdsa_crypto::AuthorityId,
67 >,
68 BabeCreateInherentDataProviders<Block>,
69 ChainSelection,
70 >,
71 sc_consensus_grandpa::LinkHalf<Block, FullClient, ChainSelection>,
72 sc_consensus_babe::BabeLink<Block>,
73 sc_consensus_beefy::BeefyVoterLinks<Block, ecdsa_crypto::AuthorityId>,
74 ),
75 sc_consensus_grandpa::SharedVoterState,
76 sp_consensus_babe::SlotDuration,
77 Option<Telemetry>,
78 ),
79>;
80
81pub(crate) struct Basics {
82 pub(crate) task_manager: TaskManager,
83 pub(crate) client: Arc<FullClient>,
84 pub(crate) backend: Arc<FullBackend>,
85 pub(crate) keystore_container: KeystoreContainer,
86 pub(crate) telemetry: Option<Telemetry>,
87}
88
89pub(crate) fn new_partial_basics(
90 config: &mut Configuration,
91 telemetry_worker_handle: Option<TelemetryWorkerHandle>,
92) -> Result<Basics, Error> {
93 let telemetry = config
94 .telemetry_endpoints
95 .clone()
96 .filter(|x| !x.is_empty())
97 .map(move |endpoints| -> Result<_, sc_telemetry::Error> {
98 let (worker, mut worker_handle) = if let Some(worker_handle) = telemetry_worker_handle {
99 (None, worker_handle)
100 } else {
101 let worker = TelemetryWorker::new(16)?;
102 let worker_handle = worker.handle();
103 (Some(worker), worker_handle)
104 };
105 let telemetry = worker_handle.new_telemetry(endpoints);
106 Ok((worker, telemetry))
107 })
108 .transpose()?;
109
110 let heap_pages = config
111 .executor
112 .default_heap_pages
113 .map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static { extra_pages: h as _ });
114
115 let executor = WasmExecutor::builder()
116 .with_execution_method(config.executor.wasm_method)
117 .with_onchain_heap_alloc_strategy(heap_pages)
118 .with_offchain_heap_alloc_strategy(heap_pages)
119 .with_max_runtime_instances(config.executor.max_runtime_instances)
120 .with_runtime_cache_size(config.executor.runtime_cache_size)
121 .build();
122
123 let (client, backend, keystore_container, task_manager) =
124 sc_service::new_full_parts::<Block, RuntimeApi, _>(
125 &config,
126 telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
127 executor,
128 )?;
129 let client = Arc::new(client);
130
131 let telemetry = telemetry.map(|(worker, telemetry)| {
132 if let Some(worker) = worker {
133 task_manager.spawn_handle().spawn(
134 "telemetry",
135 Some("telemetry"),
136 Box::pin(worker.run()),
137 );
138 }
139 telemetry
140 });
141
142 Ok(Basics { task_manager, client, backend, keystore_container, telemetry })
143}
144
145pub(crate) fn new_partial<ChainSelection>(
146 config: &mut Configuration,
147 Basics { task_manager, backend, client, keystore_container, telemetry }: Basics,
148 select_chain: ChainSelection,
149) -> Result<PolkadotPartialComponents<ChainSelection>, Error>
150where
151 ChainSelection: 'static + SelectChain<Block>,
152{
153 let transaction_pool = Arc::from(
154 sc_transaction_pool::Builder::new(
155 task_manager.spawn_essential_handle(),
156 client.clone(),
157 config.role.is_authority().into(),
158 )
159 .with_options(config.transaction_pool.clone())
160 .with_prometheus(config.prometheus_registry())
161 .build(),
162 );
163
164 let grandpa_hard_forks = if config.chain_spec.is_kusama() {
165 grandpa_support::kusama_hard_forks()
166 } else {
167 Vec::new()
168 };
169
170 let (grandpa_block_import, grandpa_link) =
171 sc_consensus_grandpa::block_import_with_authority_set_hard_forks(
172 client.clone(),
173 GRANDPA_JUSTIFICATION_PERIOD,
174 &client.clone(),
175 select_chain.clone(),
176 grandpa_hard_forks,
177 telemetry.as_ref().map(|x| x.handle()),
178 )?;
179 let justification_import = grandpa_block_import.clone();
180
181 let (beefy_block_import, beefy_voter_links, beefy_rpc_links) =
182 sc_consensus_beefy::beefy_block_import_and_links(
183 grandpa_block_import,
184 backend.clone(),
185 client.clone(),
186 config.prometheus_registry().cloned(),
187 );
188
189 let babe_config = sc_consensus_babe::configuration(&*client)?;
190 let slot_duration = babe_config.slot_duration();
191 let (block_import, babe_link) = sc_consensus_babe::block_import(
192 babe_config.clone(),
193 beefy_block_import,
194 client.clone(),
195 Arc::new(move |_, _| async move {
196 let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
197 let slot = sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_slot_duration(
198 *timestamp,
199 slot_duration,
200 );
201 Ok((slot, timestamp))
202 }) as BabeCreateInherentDataProviders<Block>,
203 select_chain.clone(),
204 OffchainTransactionPoolFactory::new(transaction_pool.clone()),
205 )?;
206
207 let (import_queue, babe_worker_handle) =
208 sc_consensus_babe::import_queue(sc_consensus_babe::ImportQueueParams {
209 link: babe_link.clone(),
210 block_import: block_import.clone(),
211 justification_import: Some(Box::new(justification_import)),
212 client: client.clone(),
213 slot_duration,
214 spawner: &task_manager.spawn_essential_handle(),
215 registry: config.prometheus_registry(),
216 telemetry: telemetry.as_ref().map(|x| x.handle()),
217 })?;
218
219 let justification_stream = grandpa_link.justification_stream();
220 let shared_authority_set = grandpa_link.shared_authority_set().clone();
221 let shared_voter_state = sc_consensus_grandpa::SharedVoterState::empty();
222 let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service(
223 backend.clone(),
224 Some(shared_authority_set.clone()),
225 );
226
227 let import_setup = (block_import, grandpa_link, babe_link, beefy_voter_links);
228 let rpc_setup = shared_voter_state.clone();
229
230 let rpc_extensions_builder = {
231 let client = client.clone();
232 let keystore = keystore_container.keystore();
233 let transaction_pool = transaction_pool.clone();
234 let select_chain = select_chain.clone();
235 let chain_spec = config.chain_spec.cloned_box();
236 let backend = backend.clone();
237
238 move |subscription_executor: polkadot_rpc::SubscriptionTaskExecutor|
239 -> Result<polkadot_rpc::RpcExtension, sc_service::Error> {
240 let deps = polkadot_rpc::FullDeps {
241 client: client.clone(),
242 pool: transaction_pool.clone(),
243 select_chain: select_chain.clone(),
244 chain_spec: chain_spec.cloned_box(),
245 babe: polkadot_rpc::BabeDeps {
246 babe_worker_handle: babe_worker_handle.clone(),
247 keystore: keystore.clone(),
248 },
249 grandpa: polkadot_rpc::GrandpaDeps {
250 shared_voter_state: shared_voter_state.clone(),
251 shared_authority_set: shared_authority_set.clone(),
252 justification_stream: justification_stream.clone(),
253 subscription_executor: subscription_executor.clone(),
254 finality_provider: finality_proof_provider.clone(),
255 },
256 beefy: polkadot_rpc::BeefyDeps::<ecdsa_crypto::AuthorityId> {
257 beefy_finality_proof_stream: beefy_rpc_links.from_voter_justif_stream.clone(),
258 beefy_best_block_stream: beefy_rpc_links.from_voter_best_beefy_stream.clone(),
259 subscription_executor,
260 },
261 backend: backend.clone(),
262 };
263
264 polkadot_rpc::create_full(deps).map_err(Into::into)
265 }
266 };
267
268 Ok(sc_service::PartialComponents {
269 client,
270 backend,
271 task_manager,
272 keystore_container,
273 select_chain,
274 import_queue,
275 transaction_pool,
276 other: (
277 Box::new(rpc_extensions_builder),
278 import_setup,
279 rpc_setup,
280 slot_duration,
281 telemetry,
282 ),
283 })
284}