1use crate::dsn::DsnConfig;
2use sc_chain_spec::ChainSpec;
3use sc_consensus_subspace::archiver::CreateObjectMappings;
4use sc_network::config::{
5 MultiaddrWithPeerId, NetworkBackendType, NetworkConfiguration, NodeKeyConfig, SetConfig,
6 SyncMode, TransportConfig, DEFAULT_KADEMLIA_REPLICATION_FACTOR,
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::atomic::AtomicBool;
25use std::sync::Arc;
26use subspace_data_retrieval::piece_getter::PieceGetter;
27use subspace_networking::libp2p::Multiaddr;
28use subspace_networking::Node;
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 yamux_window_size: None,
208 network_backend: NetworkBackendType::Libp2p,
209 force_synced: configuration.network.force_synced,
210 },
211 keystore: KeystoreConfig::InMemory,
213 database: DatabaseSource::ParityDb {
214 path: configuration.base_path.join("db"),
215 },
216 data_path: configuration.base_path.clone(),
217 trie_cache_maximum_size: configuration.trie_cache_size,
218 state_pruning: Some(configuration.state_pruning),
219 blocks_pruning: configuration.blocks_pruning,
220 executor: configuration.executor,
221 wasm_runtime_overrides: None,
222 rpc: RpcConfiguration {
223 addr: rpc_addr,
224 methods: configuration.rpc_options.methods,
225 max_connections: configuration.rpc_options.max_connections,
226 cors: configuration.rpc_options.cors,
227 max_request_size: RPC_DEFAULT_MAX_REQUEST_SIZE_MB,
228 max_response_size: RPC_DEFAULT_MAX_RESPONSE_SIZE_MB,
229 id_provider: None,
230 max_subs_per_conn: configuration.rpc_options.max_subscriptions_per_connection,
231 port: 0,
233 message_buffer_capacity: configuration
234 .rpc_options
235 .message_buffer_capacity_per_connection,
236 batch_config: rpc_batch_config,
237 rate_limit: configuration.rpc_options.rate_limit,
238 rate_limit_whitelisted_ips: configuration.rpc_options.rate_limit_whitelisted_ips,
239 rate_limit_trust_proxy_headers: configuration
240 .rpc_options
241 .rate_limit_trust_proxy_headers,
242 },
243 prometheus_config: configuration
244 .prometheus_listen_on
245 .map(|prometheus_listen_on| {
246 PrometheusConfig::new_with_default_registry(
247 prometheus_listen_on,
248 configuration.chain_spec.id().to_string(),
249 )
250 }),
251 telemetry_endpoints: configuration.telemetry_endpoints,
252 offchain_worker: OffchainWorkerConfig {
255 enabled: false,
256 indexing_enabled: true,
257 },
258 force_authoring: configuration.force_authoring,
259 disable_grandpa: true,
260 dev_key_seed: None,
261 tracing_targets: None,
262 tracing_receiver: Default::default(),
263 chain_spec: configuration.chain_spec,
264 announce_block: true,
266 role: if configuration.farmer {
267 sc_service::Role::Authority
268 } else {
269 sc_service::Role::Full
270 },
271 base_path: BasePath::new(configuration.base_path),
272 }
273 }
274}
275
276#[derive(Debug)]
278#[allow(clippy::large_enum_variant)]
279pub enum SubspaceNetworking {
280 Reuse {
282 node: Node,
284 bootstrap_nodes: Vec<Multiaddr>,
286 piece_getter: Arc<dyn PieceGetter + Send + Sync + 'static>,
288 },
289 Create {
291 config: DsnConfig,
293 },
294}
295
296#[derive(Debug)]
298pub struct SubspaceConfiguration {
299 pub base: Configuration,
301 pub force_new_slot_notifications: bool,
304 pub create_object_mappings: CreateObjectMappings,
306 pub subspace_networking: SubspaceNetworking,
308 pub is_timekeeper: bool,
310 pub timekeeper_cpu_cores: HashSet<usize>,
312 pub sync: ChainSyncMode,
314}
315
316#[derive(Debug, Clone, Copy, PartialEq)]
318pub enum ChainSyncMode {
319 Full,
321 Snap,
323}
324
325impl FromStr for ChainSyncMode {
326 type Err = String;
327
328 fn from_str(input: &str) -> Result<Self, Self::Err> {
329 match input {
330 "full" => Ok(Self::Full),
331 "snap" => Ok(Self::Snap),
332 _ => Err("Unsupported sync type: use full or snap".to_string()),
333 }
334 }
335}
336
337impl fmt::Display for ChainSyncMode {
338 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
339 match self {
340 Self::Full => f.write_str("full"),
341 Self::Snap => f.write_str("snap"),
342 }
343 }
344}
345
346impl Default for ChainSyncMode {
347 fn default() -> Self {
348 Self::Full
349 }
350}
351
352impl Deref for SubspaceConfiguration {
353 type Target = Configuration;
354
355 fn deref(&self) -> &Self::Target {
356 &self.base
357 }
358}