1use crate::dsn::DsnConfig;
2use sc_chain_spec::ChainSpec;
3use sc_consensus_subspace::archiver::CreateObjectMappings;
4use sc_network::config::{
5 DEFAULT_KADEMLIA_REPLICATION_FACTOR, MultiaddrWithPeerId, NetworkBackendType,
6 NetworkConfiguration, NodeKeyConfig, SetConfig, SyncMode, TransportConfig,
7};
8use sc_service::config::{
9 ExecutorConfiguration, IpNetwork, KeystoreConfig, OffchainWorkerConfig, PrometheusConfig,
10 RpcBatchRequestConfig, RpcConfiguration, RpcEndpoint,
11};
12use sc_service::{
13 BasePath, BlocksPruning, Configuration, DatabaseSource, PruningMode, RpcMethods,
14 TransactionPoolOptions,
15};
16use sc_telemetry::TelemetryEndpoints;
17use std::collections::HashSet;
18use std::fmt;
19use std::net::SocketAddr;
20use std::num::{NonZeroU32, NonZeroUsize};
21use std::ops::Deref;
22use std::path::PathBuf;
23use std::str::FromStr;
24use std::sync::Arc;
25use std::sync::atomic::AtomicBool;
26use subspace_data_retrieval::piece_getter::PieceGetter;
27use subspace_networking::Node;
28use subspace_networking::libp2p::Multiaddr;
29use tokio::runtime::Handle;
30
31pub const RPC_DEFAULT_MAX_REQUEST_SIZE_MB: u32 = 15;
33pub const RPC_DEFAULT_MAX_RESPONSE_SIZE_MB: u32 = 15;
35
36#[derive(Debug)]
38pub struct SubstrateRpcConfiguration {
39 pub listen_on: Option<SocketAddr>,
41 pub max_connections: u32,
43 pub cors: Option<Vec<String>>,
45 pub methods: RpcMethods,
47 pub rate_limit: Option<NonZeroU32>,
49 pub rate_limit_whitelisted_ips: Vec<IpNetwork>,
51 pub rate_limit_trust_proxy_headers: bool,
53 pub max_subscriptions_per_connection: u32,
55 pub message_buffer_capacity_per_connection: u32,
57 pub disable_batch_requests: bool,
59 pub max_batch_request_len: Option<u32>,
61}
62
63#[derive(Debug)]
65pub struct SubstrateNetworkConfiguration {
66 pub listen_on: Vec<sc_network::Multiaddr>,
68 pub public_addresses: Vec<sc_network::Multiaddr>,
70 pub bootstrap_nodes: Vec<MultiaddrWithPeerId>,
72 pub node_key: NodeKeyConfig,
74 pub default_peers_set: SetConfig,
76 pub node_name: String,
78 pub allow_private_ips: bool,
81 pub sync_mode: ChainSyncMode,
83 pub force_synced: bool,
87}
88
89#[derive(Debug)]
92pub struct SubstrateConfiguration {
93 pub impl_name: String,
95 pub impl_version: String,
97 pub farmer: bool,
99 pub base_path: PathBuf,
101 pub transaction_pool: TransactionPoolOptions,
103 pub network: SubstrateNetworkConfiguration,
105 pub state_pruning: PruningMode,
107 pub blocks_pruning: BlocksPruning,
111 pub rpc_options: SubstrateRpcConfiguration,
113 pub prometheus_listen_on: Option<SocketAddr>,
115 pub telemetry_endpoints: Option<TelemetryEndpoints>,
117 pub force_authoring: bool,
119 pub chain_spec: Box<dyn ChainSpec>,
121 pub executor: ExecutorConfiguration,
123 pub trie_cache_size: Option<usize>,
125}
126
127impl From<SubstrateConfiguration> for Configuration {
128 fn from(configuration: SubstrateConfiguration) -> Self {
129 let net_config_path = configuration.base_path.join("network");
130 let default_peers_set_num_full = configuration.network.default_peers_set.in_peers
131 + configuration.network.default_peers_set.out_peers;
132 let client_version = format!("{}/{}", configuration.impl_name, configuration.impl_version);
133
134 let rpc_batch_config = if configuration.rpc_options.disable_batch_requests {
135 RpcBatchRequestConfig::Disabled
136 } else if let Some(l) = configuration.rpc_options.max_batch_request_len {
137 RpcBatchRequestConfig::Limit(l)
138 } else {
139 RpcBatchRequestConfig::Unlimited
140 };
141 let rpc_addr = configuration.rpc_options.listen_on.map(|listen_addr| {
142 vec![RpcEndpoint {
143 batch_config: rpc_batch_config,
144 max_connections: configuration.rpc_options.max_connections,
145 listen_addr,
146 rpc_methods: configuration.rpc_options.methods,
147 rate_limit: configuration.rpc_options.rate_limit,
148 rate_limit_trust_proxy_headers: configuration
149 .rpc_options
150 .rate_limit_trust_proxy_headers,
151 rate_limit_whitelisted_ips: configuration
152 .rpc_options
153 .rate_limit_whitelisted_ips
154 .clone(),
155 max_payload_in_mb: RPC_DEFAULT_MAX_REQUEST_SIZE_MB,
156 max_payload_out_mb: RPC_DEFAULT_MAX_RESPONSE_SIZE_MB,
157 max_subscriptions_per_connection: configuration
158 .rpc_options
159 .max_subscriptions_per_connection,
160 max_buffer_capacity_per_connection: configuration
161 .rpc_options
162 .message_buffer_capacity_per_connection,
163 cors: configuration.rpc_options.cors.clone(),
164 retry_random_port: true,
165 is_optional: false,
166 }]
167 });
168
169 Self {
170 impl_name: configuration.impl_name,
171 impl_version: configuration.impl_version,
172 tokio_handle: Handle::current(),
173 transaction_pool: configuration.transaction_pool,
174 network: NetworkConfiguration {
175 net_config_path: Some(net_config_path.clone()),
176 listen_addresses: configuration.network.listen_on,
177 public_addresses: configuration.network.public_addresses,
178 boot_nodes: if !configuration.network.bootstrap_nodes.is_empty() {
179 configuration.network.bootstrap_nodes
180 } else {
181 configuration.chain_spec.boot_nodes().to_vec()
182 },
183 node_key: configuration.network.node_key,
184 default_peers_set: configuration.network.default_peers_set,
185 default_peers_set_num_full,
186 client_version,
187 node_name: configuration.network.node_name,
188 transport: TransportConfig::Normal {
189 enable_mdns: false,
190 allow_private_ip: configuration.network.allow_private_ips,
191 },
192 max_parallel_downloads: 5,
194 max_blocks_per_request: 64,
196 sync_mode: SyncMode::Full,
197 pause_sync: Arc::new(AtomicBool::new(false)),
198 enable_dht_random_walk: true,
200 allow_non_globals_in_dht: configuration.network.allow_private_ips,
202 kademlia_disjoint_query_paths: false,
204 kademlia_replication_factor: NonZeroUsize::new(DEFAULT_KADEMLIA_REPLICATION_FACTOR)
205 .expect("value is a constant; constant is non-zero; qed"),
206 ipfs_server: false,
207 network_backend: NetworkBackendType::Libp2p,
208 force_synced: configuration.network.force_synced,
209 },
210 keystore: KeystoreConfig::InMemory,
212 database: DatabaseSource::ParityDb {
213 path: configuration.base_path.join("db"),
214 },
215 data_path: configuration.base_path.clone(),
216 trie_cache_maximum_size: configuration.trie_cache_size,
217 state_pruning: Some(configuration.state_pruning),
218 blocks_pruning: configuration.blocks_pruning,
219 executor: configuration.executor,
220 wasm_runtime_overrides: None,
221 rpc: RpcConfiguration {
222 addr: rpc_addr,
223 methods: configuration.rpc_options.methods,
224 max_connections: configuration.rpc_options.max_connections,
225 cors: configuration.rpc_options.cors,
226 max_request_size: RPC_DEFAULT_MAX_REQUEST_SIZE_MB,
227 max_response_size: RPC_DEFAULT_MAX_RESPONSE_SIZE_MB,
228 id_provider: None,
229 max_subs_per_conn: configuration.rpc_options.max_subscriptions_per_connection,
230 port: 0,
232 message_buffer_capacity: configuration
233 .rpc_options
234 .message_buffer_capacity_per_connection,
235 batch_config: rpc_batch_config,
236 rate_limit: configuration.rpc_options.rate_limit,
237 rate_limit_whitelisted_ips: configuration.rpc_options.rate_limit_whitelisted_ips,
238 rate_limit_trust_proxy_headers: configuration
239 .rpc_options
240 .rate_limit_trust_proxy_headers,
241 },
242 prometheus_config: configuration
243 .prometheus_listen_on
244 .map(|prometheus_listen_on| {
245 PrometheusConfig::new_with_default_registry(
246 prometheus_listen_on,
247 configuration.chain_spec.id().to_string(),
248 )
249 }),
250 telemetry_endpoints: configuration.telemetry_endpoints,
251 offchain_worker: OffchainWorkerConfig {
254 enabled: false,
255 indexing_enabled: true,
256 },
257 force_authoring: configuration.force_authoring,
258 disable_grandpa: true,
259 dev_key_seed: None,
260 tracing_targets: None,
261 tracing_receiver: Default::default(),
262 chain_spec: configuration.chain_spec,
263 announce_block: true,
265 role: if configuration.farmer {
266 sc_service::Role::Authority
267 } else {
268 sc_service::Role::Full
269 },
270 base_path: BasePath::new(configuration.base_path),
271 }
272 }
273}
274
275#[derive(Debug)]
277#[allow(clippy::large_enum_variant)]
278pub enum SubspaceNetworking {
279 Reuse {
281 node: Node,
283 bootstrap_nodes: Vec<Multiaddr>,
285 piece_getter: Arc<dyn PieceGetter + Send + Sync + 'static>,
287 },
288 Create {
290 config: DsnConfig,
292 },
293}
294
295#[derive(Debug)]
297pub struct SubspaceConfiguration {
298 pub base: Configuration,
300 pub force_new_slot_notifications: bool,
303 pub create_object_mappings: CreateObjectMappings,
305 pub subspace_networking: SubspaceNetworking,
307 pub is_timekeeper: bool,
309 pub timekeeper_cpu_cores: HashSet<usize>,
311 pub sync: ChainSyncMode,
313}
314
315#[derive(Debug, Clone, Copy, PartialEq)]
317pub enum ChainSyncMode {
318 Full,
320 Snap,
322}
323
324impl FromStr for ChainSyncMode {
325 type Err = String;
326
327 fn from_str(input: &str) -> Result<Self, Self::Err> {
328 match input {
329 "full" => Ok(Self::Full),
330 "snap" => Ok(Self::Snap),
331 _ => Err("Unsupported sync type: use full or snap".to_string()),
332 }
333 }
334}
335
336impl fmt::Display for ChainSyncMode {
337 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
338 match self {
339 Self::Full => f.write_str("full"),
340 Self::Snap => f.write_str("snap"),
341 }
342 }
343}
344
345impl Default for ChainSyncMode {
346 fn default() -> Self {
347 Self::Full
348 }
349}
350
351impl Deref for SubspaceConfiguration {
352 type Target = Configuration;
353
354 fn deref(&self) -> &Self::Target {
355 &self.base
356 }
357}