Skip to main content

sc_service/
config.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! Service configuration.
20
21pub use jsonrpsee::server::BatchRequestConfig as RpcBatchRequestConfig;
22use prometheus_endpoint::Registry;
23use sc_chain_spec::ChainSpec;
24pub use sc_client_db::{BlocksPruning, Database, DatabaseSource, PruningMode};
25pub use sc_executor::{WasmExecutionMethod, WasmtimeInstantiationStrategy};
26pub use sc_network::{
27	config::{
28		MultiaddrWithPeerId, NetworkConfiguration, NodeKeyConfig, NonDefaultSetConfig, ProtocolId,
29		Role, SetConfig, SyncMode, TransportConfig,
30	},
31	request_responses::{
32		IncomingRequest, OutgoingResponse, ProtocolConfig as RequestResponseConfig,
33	},
34	Multiaddr,
35};
36pub use sc_rpc_server::{
37	IpNetwork, RpcEndpoint, RpcMethods, SubscriptionIdProvider as RpcSubscriptionIdProvider,
38};
39pub use sc_telemetry::TelemetryEndpoints;
40pub use sc_transaction_pool::TransactionPoolOptions;
41use sp_core::crypto::SecretString;
42use std::{
43	io, iter,
44	net::SocketAddr,
45	num::NonZeroU32,
46	path::{Path, PathBuf},
47};
48use tempfile::TempDir;
49
50/// Service configuration.
51#[derive(Debug)]
52pub struct Configuration {
53	/// Implementation name
54	pub impl_name: String,
55	/// Implementation version (see sc-cli to see an example of format)
56	pub impl_version: String,
57	/// Node role.
58	pub role: Role,
59	/// Handle to the tokio runtime. Will be used to spawn futures by the task manager.
60	pub tokio_handle: tokio::runtime::Handle,
61	/// Extrinsic pool configuration.
62	pub transaction_pool: TransactionPoolOptions,
63	/// Network configuration.
64	pub network: NetworkConfiguration,
65	/// Configuration for the keystore.
66	pub keystore: KeystoreConfig,
67	/// Configuration for the database.
68	pub database: DatabaseSource,
69	/// Maximum size of internal trie cache in bytes.
70	///
71	/// If `None` is given the cache is disabled.
72	pub trie_cache_maximum_size: Option<usize>,
73	/// Force the trie cache to be in memory.
74	pub warm_up_trie_cache: Option<TrieCacheWarmUpStrategy>,
75	/// State pruning settings.
76	pub state_pruning: Option<PruningMode>,
77	/// Number of blocks to keep in the db.
78	///
79	/// NOTE: only finalized blocks are subject for removal!
80	pub blocks_pruning: BlocksPruning,
81	/// Chain configuration.
82	pub chain_spec: Box<dyn ChainSpec>,
83	/// Runtime executor configuration.
84	pub executor: ExecutorConfiguration,
85	/// Directory where local WASM runtimes live. These runtimes take precedence
86	/// over on-chain runtimes when the spec version matches. Set to `None` to
87	/// disable overrides (default).
88	pub wasm_runtime_overrides: Option<PathBuf>,
89	/// RPC configuration.
90	pub rpc: RpcConfiguration,
91	/// Prometheus endpoint configuration. `None` if disabled.
92	pub prometheus_config: Option<PrometheusConfig>,
93	/// Telemetry service URL. `None` if disabled.
94	pub telemetry_endpoints: Option<TelemetryEndpoints>,
95	/// Should offchain workers be executed.
96	pub offchain_worker: OffchainWorkerConfig,
97	/// Enable authoring even when offline.
98	pub force_authoring: bool,
99	/// Disable GRANDPA when running in validator mode
100	pub disable_grandpa: bool,
101	/// Development key seed.
102	///
103	/// When running in development mode, the seed will be used to generate authority keys by the
104	/// keystore.
105	///
106	/// Should only be set when `node` is running development mode.
107	pub dev_key_seed: Option<String>,
108	/// Tracing targets
109	pub tracing_targets: Option<String>,
110	/// Tracing receiver
111	pub tracing_receiver: sc_tracing::TracingReceiver,
112	/// Announce block automatically after they have been imported
113	pub announce_block: bool,
114	/// Data path root for the configured chain.
115	pub data_path: PathBuf,
116	/// Base path of the configuration. This is shared between chains.
117	pub base_path: BasePath,
118}
119
120/// Warmup strategy for the trie cache.
121#[derive(Debug, Clone, Copy)]
122pub enum TrieCacheWarmUpStrategy {
123	/// Warm up the cache in a non-blocking way.
124	NonBlocking,
125	/// Warm up the cache in a blocking way.
126	Blocking,
127}
128
129impl TrieCacheWarmUpStrategy {
130	/// Returns true if the warmup strategy is blocking.
131	pub(crate) fn is_blocking(&self) -> bool {
132		matches!(self, Self::Blocking)
133	}
134}
135
136/// Type for tasks spawned by the executor.
137#[derive(PartialEq)]
138pub enum TaskType {
139	/// Regular non-blocking futures. Polling the task is expected to be a lightweight operation.
140	Async,
141	/// The task might perform a lot of expensive CPU operations and/or call `thread::sleep`.
142	Blocking,
143}
144
145/// Configuration of the client keystore.
146#[derive(Debug, Clone)]
147pub enum KeystoreConfig {
148	/// Keystore at a path on-disk. Recommended for native nodes.
149	Path {
150		/// The path of the keystore.
151		path: PathBuf,
152		/// Node keystore's password.
153		password: Option<SecretString>,
154	},
155	/// In-memory keystore. Recommended for in-browser nodes.
156	InMemory,
157}
158
159impl KeystoreConfig {
160	/// Returns the path for the keystore.
161	pub fn path(&self) -> Option<&Path> {
162		match self {
163			Self::Path { path, .. } => Some(path),
164			Self::InMemory => None,
165		}
166	}
167}
168/// Configuration of the database of the client.
169#[derive(Debug, Clone, Default)]
170pub struct OffchainWorkerConfig {
171	/// If this is allowed.
172	pub enabled: bool,
173	/// allow writes from the runtime to the offchain worker database.
174	pub indexing_enabled: bool,
175}
176
177/// Configuration of the Prometheus endpoint.
178#[derive(Debug, Clone)]
179pub struct PrometheusConfig {
180	/// Port to use.
181	pub port: SocketAddr,
182	/// A metrics registry to use. Useful for setting the metric prefix.
183	pub registry: Registry,
184}
185
186impl PrometheusConfig {
187	/// Create a new config using the default registry.
188	pub fn new_with_default_registry(port: SocketAddr, chain_id: String) -> Self {
189		let param = iter::once((String::from("chain"), chain_id)).collect();
190		Self {
191			port,
192			registry: Registry::new_custom(None, Some(param))
193				.expect("this can only fail if the prefix is empty"),
194		}
195	}
196}
197
198impl Configuration {
199	/// Returns a string displaying the node role.
200	pub fn display_role(&self) -> String {
201		self.role.to_string()
202	}
203
204	/// Returns the prometheus metrics registry, if available.
205	pub fn prometheus_registry(&self) -> Option<&Registry> {
206		self.prometheus_config.as_ref().map(|config| &config.registry)
207	}
208
209	/// Returns the network protocol id from the chain spec, or the default.
210	pub fn protocol_id(&self) -> ProtocolId {
211		let protocol_id_full = match self.chain_spec.protocol_id() {
212			Some(pid) => pid,
213			None => {
214				log::warn!(
215					"Using default protocol ID {:?} because none is configured in the \
216					chain specs",
217					crate::DEFAULT_PROTOCOL_ID
218				);
219				crate::DEFAULT_PROTOCOL_ID
220			},
221		};
222		ProtocolId::from(protocol_id_full)
223	}
224
225	/// Returns true if the genesis state writing will be skipped while initializing the genesis
226	/// block.
227	pub fn no_genesis(&self) -> bool {
228		matches!(self.network.sync_mode, SyncMode::LightState { .. } | SyncMode::Warp { .. })
229	}
230
231	/// Returns the database config for creating the backend.
232	pub fn db_config(&self) -> sc_client_db::DatabaseSettings {
233		sc_client_db::DatabaseSettings {
234			trie_cache_maximum_size: self.trie_cache_maximum_size,
235			state_pruning: self.state_pruning.clone(),
236			source: self.database.clone(),
237			blocks_pruning: self.blocks_pruning,
238			pruning_filters: Default::default(),
239			metrics_registry: self.prometheus_registry().cloned(),
240		}
241	}
242}
243
244#[static_init::dynamic(drop, lazy)]
245static mut BASE_PATH_TEMP: Option<TempDir> = None;
246
247/// The base path that is used for everything that needs to be written on disk to run a node.
248#[derive(Clone, Debug)]
249pub struct BasePath {
250	path: PathBuf,
251}
252
253impl BasePath {
254	/// Create a `BasePath` instance using a temporary directory prefixed with "substrate" and use
255	/// it as base path.
256	///
257	/// Note: The temporary directory will be created automatically and deleted when the program
258	/// exits. Every call to this function will return the same path for the lifetime of the
259	/// program.
260	pub fn new_temp_dir() -> io::Result<BasePath> {
261		let mut temp = BASE_PATH_TEMP.write();
262
263		match &*temp {
264			Some(p) => Ok(Self::new(p.path())),
265			None => {
266				let temp_dir = tempfile::Builder::new().prefix("substrate").tempdir()?;
267				let path = PathBuf::from(temp_dir.path());
268
269				*temp = Some(temp_dir);
270				Ok(Self::new(path))
271			},
272		}
273	}
274
275	/// Create a `BasePath` instance based on an existing path on disk.
276	///
277	/// Note: this function will not ensure that the directory exist nor create the directory. It
278	/// will also not delete the directory when the instance is dropped.
279	pub fn new<P: Into<PathBuf>>(path: P) -> BasePath {
280		Self { path: path.into() }
281	}
282
283	/// Create a base path from values describing the project.
284	pub fn from_project(qualifier: &str, organization: &str, application: &str) -> BasePath {
285		BasePath::new(
286			directories::ProjectDirs::from(qualifier, organization, application)
287				.expect("app directories exist on all supported platforms; qed")
288				.data_local_dir(),
289		)
290	}
291
292	/// Retrieve the base path.
293	pub fn path(&self) -> &Path {
294		&self.path
295	}
296
297	/// Returns the configuration directory inside this base path.
298	///
299	/// The path looks like `$base_path/chains/$chain_id`
300	pub fn config_dir(&self, chain_id: &str) -> PathBuf {
301		self.path().join("chains").join(chain_id)
302	}
303}
304
305impl From<PathBuf> for BasePath {
306	fn from(path: PathBuf) -> Self {
307		BasePath::new(path)
308	}
309}
310
311/// RPC configuration.
312#[derive(Debug)]
313pub struct RpcConfiguration {
314	/// JSON-RPC server endpoints.
315	pub addr: Option<Vec<RpcEndpoint>>,
316	/// Maximum number of connections for JSON-RPC server.
317	pub max_connections: u32,
318	/// CORS settings for HTTP & WS servers. `None` if all origins are allowed.
319	pub cors: Option<Vec<String>>,
320	/// RPC methods to expose (by default only a safe subset or all of them).
321	pub methods: RpcMethods,
322	/// Maximum payload of a rpc request
323	pub max_request_size: u32,
324	/// Maximum payload of a rpc response.
325	pub max_response_size: u32,
326	/// Custom JSON-RPC subscription ID provider.
327	///
328	/// Default: [`crate::RandomStringSubscriptionId`].
329	pub id_provider: Option<Box<dyn RpcSubscriptionIdProvider>>,
330	/// Maximum allowed subscriptions per rpc connection
331	pub max_subs_per_conn: u32,
332	/// JSON-RPC server default port.
333	pub port: u16,
334	/// The number of messages the JSON-RPC server is allowed to keep in memory.
335	pub message_buffer_capacity: u32,
336	/// JSON-RPC server batch config.
337	pub batch_config: RpcBatchRequestConfig,
338	/// RPC rate limit per minute.
339	pub rate_limit: Option<NonZeroU32>,
340	/// RPC rate limit whitelisted ip addresses.
341	pub rate_limit_whitelisted_ips: Vec<IpNetwork>,
342	/// RPC rate limit trust proxy headers.
343	pub rate_limit_trust_proxy_headers: bool,
344	/// RPC logger capacity (default: 1024).
345	pub request_logger_limit: u32,
346}
347
348/// Runtime executor configuration.
349#[derive(Debug, Clone)]
350pub struct ExecutorConfiguration {
351	/// Wasm execution method.
352	pub wasm_method: WasmExecutionMethod,
353	/// The size of the instances cache.
354	///
355	/// The default value is 8.
356	pub max_runtime_instances: usize,
357	/// The default number of 64KB pages to allocate for Wasm execution
358	pub default_heap_pages: Option<u64>,
359	/// Maximum number of different runtime versions that can be cached.
360	pub runtime_cache_size: u8,
361}
362
363impl Default for ExecutorConfiguration {
364	fn default() -> Self {
365		Self {
366			wasm_method: WasmExecutionMethod::default(),
367			max_runtime_instances: 8,
368			default_heap_pages: None,
369			runtime_cache_size: 2,
370		}
371	}
372}