1use crate::cli::Consensus;
19use futures::FutureExt;
20use polkadot_sdk::{
21 sc_client_api::backend::Backend,
22 sc_executor::WasmExecutor,
23 sc_service::{error::Error as ServiceError, Configuration, TaskManager},
24 sc_telemetry::{Telemetry, TelemetryWorker},
25 sc_transaction_pool_api::OffchainTransactionPoolFactory,
26 sp_runtime::traits::Block as BlockT,
27 *,
28};
29use revive_dev_runtime::{OpaqueBlock as Block, RuntimeApi};
30use std::sync::Arc;
31
32type HostFunctions = sp_io::SubstrateHostFunctions;
33
34#[docify::export]
35pub(crate) type FullClient =
36 sc_service::TFullClient<Block, RuntimeApi, WasmExecutor<HostFunctions>>;
37
38type FullBackend = sc_service::TFullBackend<Block>;
39type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;
40
41pub type Service = sc_service::PartialComponents<
43 FullClient,
44 FullBackend,
45 FullSelectChain,
46 sc_consensus::DefaultImportQueue<Block>,
47 sc_transaction_pool::TransactionPoolHandle<Block, FullClient>,
48 Option<Telemetry>,
49>;
50
51pub fn new_partial(config: &Configuration) -> Result<Service, ServiceError> {
52 let telemetry = config
53 .telemetry_endpoints
54 .clone()
55 .filter(|x| !x.is_empty())
56 .map(|endpoints| -> Result<_, sc_telemetry::Error> {
57 let worker = TelemetryWorker::new(16)?;
58 let telemetry = worker.handle().new_telemetry(endpoints);
59 Ok((worker, telemetry))
60 })
61 .transpose()?;
62
63 let executor = sc_service::new_wasm_executor(&config.executor);
64
65 let (client, backend, keystore_container, task_manager) =
66 sc_service::new_full_parts::<Block, RuntimeApi, _>(
67 config,
68 telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
69 executor,
70 )?;
71 let client = Arc::new(client);
72
73 let telemetry = telemetry.map(|(worker, telemetry)| {
74 task_manager.spawn_handle().spawn("telemetry", None, worker.run());
75 telemetry
76 });
77
78 let select_chain = sc_consensus::LongestChain::new(backend.clone());
79
80 let transaction_pool = Arc::from(
81 sc_transaction_pool::Builder::new(
82 task_manager.spawn_essential_handle(),
83 client.clone(),
84 config.role.is_authority().into(),
85 )
86 .with_options(config.transaction_pool.clone())
87 .build(),
88 );
89
90 let import_queue = sc_consensus_manual_seal::import_queue(
91 Box::new(client.clone()),
92 &task_manager.spawn_essential_handle(),
93 None,
94 );
95
96 Ok(sc_service::PartialComponents {
97 client,
98 backend,
99 task_manager,
100 import_queue,
101 keystore_container,
102 select_chain,
103 transaction_pool,
104 other: (telemetry),
105 })
106}
107
108pub fn new_full<Network: sc_network::NetworkBackend<Block, <Block as BlockT>::Hash>>(
110 config: Configuration,
111 consensus: Consensus,
112) -> Result<TaskManager, ServiceError> {
113 let sc_service::PartialComponents {
114 client,
115 backend,
116 mut task_manager,
117 import_queue,
118 keystore_container,
119 select_chain,
120 transaction_pool,
121 other: mut telemetry,
122 } = new_partial(&config)?;
123
124 let net_config = sc_network::config::FullNetworkConfiguration::<
125 Block,
126 <Block as BlockT>::Hash,
127 Network,
128 >::new(&config.network, None);
129 let metrics = Network::register_notification_metrics(None);
130
131 let (network, system_rpc_tx, tx_handler_controller, sync_service) =
132 sc_service::build_network(sc_service::BuildNetworkParams {
133 config: &config,
134 net_config,
135 client: client.clone(),
136 transaction_pool: transaction_pool.clone(),
137 spawn_handle: task_manager.spawn_handle(),
138 import_queue,
139 block_announce_validator_builder: None,
140 warp_sync_config: None,
141 block_relay: None,
142 metrics,
143 })?;
144
145 if config.offchain_worker.enabled {
146 let offchain_workers =
147 sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions {
148 runtime_api_provider: client.clone(),
149 is_validator: config.role.is_authority(),
150 keystore: Some(keystore_container.keystore()),
151 offchain_db: backend.offchain_storage(),
152 transaction_pool: Some(OffchainTransactionPoolFactory::new(
153 transaction_pool.clone(),
154 )),
155 network_provider: Arc::new(network.clone()),
156 enable_http_requests: true,
157 custom_extensions: |_| vec![],
158 })?;
159 task_manager.spawn_handle().spawn(
160 "offchain-workers-runner",
161 "offchain-worker",
162 offchain_workers.run(client.clone(), task_manager.spawn_handle()).boxed(),
163 );
164 }
165
166 let rpc_extensions_builder = {
167 let client = client.clone();
168 let pool = transaction_pool.clone();
169
170 Box::new(move |_| {
171 let deps = crate::rpc::FullDeps { client: client.clone(), pool: pool.clone() };
172 crate::rpc::create_full(deps).map_err(Into::into)
173 })
174 };
175
176 let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams {
177 network,
178 client: client.clone(),
179 keystore: keystore_container.keystore(),
180 task_manager: &mut task_manager,
181 transaction_pool: transaction_pool.clone(),
182 rpc_builder: rpc_extensions_builder,
183 backend,
184 system_rpc_tx,
185 tx_handler_controller,
186 sync_service,
187 config,
188 telemetry: telemetry.as_mut(),
189 })?;
190
191 let proposer = sc_basic_authorship::ProposerFactory::new(
192 task_manager.spawn_handle(),
193 client.clone(),
194 transaction_pool.clone(),
195 None,
196 telemetry.as_ref().map(|x| x.handle()),
197 );
198
199 match consensus {
200 Consensus::InstantSeal => {
201 let params = sc_consensus_manual_seal::InstantSealParams {
202 block_import: client.clone(),
203 env: proposer,
204 client,
205 pool: transaction_pool,
206 select_chain,
207 consensus_data_provider: None,
208 create_inherent_data_providers: move |_, ()| async move {
209 Ok(sp_timestamp::InherentDataProvider::from_system_time())
210 },
211 };
212
213 let authorship_future = sc_consensus_manual_seal::run_instant_seal(params);
214
215 task_manager.spawn_essential_handle().spawn_blocking(
216 "instant-seal",
217 None,
218 authorship_future,
219 );
220 },
221 Consensus::ManualSeal(block_time) => {
222 let (mut sink, commands_stream) = futures::channel::mpsc::channel(1024);
223 task_manager.spawn_handle().spawn("block_authoring", None, async move {
224 loop {
225 futures_timer::Delay::new(std::time::Duration::from_millis(block_time)).await;
226 sink.try_send(sc_consensus_manual_seal::EngineCommand::SealNewBlock {
227 create_empty: true,
228 finalize: true,
229 parent_hash: None,
230 sender: None,
231 })
232 .unwrap();
233 }
234 });
235
236 let params = sc_consensus_manual_seal::ManualSealParams {
237 block_import: client.clone(),
238 env: proposer,
239 client,
240 pool: transaction_pool,
241 select_chain,
242 commands_stream: Box::pin(commands_stream),
243 consensus_data_provider: None,
244 create_inherent_data_providers: move |_, ()| async move {
245 Ok(sp_timestamp::InherentDataProvider::from_system_time())
246 },
247 };
248 let authorship_future = sc_consensus_manual_seal::run_manual_seal(params);
249
250 task_manager.spawn_essential_handle().spawn_blocking(
251 "manual-seal",
252 None,
253 authorship_future,
254 );
255 },
256 _ => {},
257 }
258
259 Ok(task_manager)
260}