domain_service/
config.rs

1use sc_chain_spec::ChainSpec;
2use sc_network::config::{
3    MultiaddrWithPeerId, NetworkBackendType, NetworkConfiguration, NodeKeyConfig, SetConfig,
4    SyncMode, TransportConfig, DEFAULT_KADEMLIA_REPLICATION_FACTOR,
5};
6use sc_rpc_server::RpcEndpoint;
7use sc_service::config::{
8    ExecutorConfiguration, IpNetwork, KeystoreConfig, OffchainWorkerConfig, PrometheusConfig,
9    RpcBatchRequestConfig, RpcConfiguration,
10};
11use sc_service::{
12    BasePath, BlocksPruning, Configuration, DatabaseSource, PruningMode, RpcMethods,
13    TransactionPoolOptions,
14};
15use sc_telemetry::TelemetryEndpoints;
16use std::net::SocketAddr;
17use std::num::{NonZeroU32, NonZeroUsize};
18use std::path::PathBuf;
19use std::sync::atomic::AtomicBool;
20use std::sync::Arc;
21use tokio::runtime::Handle;
22
23/// The default max request size in MB, copied from Substrate
24pub const RPC_DEFAULT_MAX_REQUEST_SIZE_MB: u32 = 15;
25/// The default max response size in MB, copied from Substrate
26pub const RPC_DEFAULT_MAX_RESPONSE_SIZE_MB: u32 = 15;
27
28/// Simplified RPC configuration used in Substrate
29#[derive(Debug)]
30pub struct SubstrateRpcConfiguration {
31    /// IP and port (TCP) on which to listen for RPC requests
32    pub listen_on: Option<SocketAddr>,
33    /// Maximum number of connections for JSON-RPC server
34    pub max_connections: u32,
35    /// CORS settings for HTTP & WS servers. `None` if all origins are allowed
36    pub cors: Option<Vec<String>>,
37    /// RPC methods to expose (by default only a safe subset or all of them)
38    pub methods: RpcMethods,
39    /// RPC rate limiting (calls/minute) for each connection
40    pub rate_limit: Option<NonZeroU32>,
41    /// Disable RPC rate limiting for certain ip addresses
42    pub rate_limit_whitelisted_ips: Vec<IpNetwork>,
43    /// Trust proxy headers for rate limiting
44    pub rate_limit_trust_proxy_headers: bool,
45    /// Maximum allowed subscriptions per rpc connection
46    pub max_subscriptions_per_connection: u32,
47    /// The number of messages the RPC server is allowed to keep in memory
48    pub message_buffer_capacity_per_connection: u32,
49    /// Disable RPC batch requests
50    pub disable_batch_requests: bool,
51    /// Limit the max length per RPC batch request
52    pub max_batch_request_len: Option<u32>,
53}
54
55/// Simplified network used in Substrate
56#[derive(Debug)]
57pub struct SubstrateNetworkConfiguration {
58    /// Multiaddresses to listen for incoming connections.
59    pub listen_on: Vec<sc_network::Multiaddr>,
60    /// Multiaddresses to advertise. Detected automatically if empty.
61    pub public_addresses: Vec<sc_network::Multiaddr>,
62    /// List of initial node addresses
63    pub bootstrap_nodes: Vec<MultiaddrWithPeerId>,
64    /// The node key configuration, which determines the node's network identity keypair.
65    pub node_key: NodeKeyConfig,
66    /// Configuration for the default set of nodes used for block syncing and transactions.
67    pub default_peers_set: SetConfig,
68    /// Name of the node. Sent over the wire for debugging purposes.
69    pub node_name: String,
70    /// Determines whether we allow keeping non-global (private, shared, loopback..) addresses
71    /// in Kademlia DHT.
72    pub allow_private_ips: bool,
73    /// Parameter that allows node to forcefully assume it is synced, needed for network
74    /// bootstrapping only, as long as two synced nodes remain on the network at any time, this
75    /// doesn't need to be used.
76    pub force_synced: bool,
77}
78
79/// Simplified Substrate configuration that can be converted into [`Configuration`] using
80/// [`From`]/[`Into`].
81#[derive(Debug)]
82pub struct SubstrateConfiguration {
83    /// Implementation name
84    pub impl_name: String,
85    /// Implementation version
86    pub impl_version: String,
87    /// Operator
88    pub operator: bool,
89    /// Base path for node data
90    pub base_path: PathBuf,
91    /// Extrinsic pool configuration
92    pub transaction_pool: TransactionPoolOptions,
93    /// Network configuration
94    pub network: SubstrateNetworkConfiguration,
95    /// Keystore configuration
96    pub keystore: KeystoreConfig,
97    /// State pruning settings
98    pub state_pruning: PruningMode,
99    /// Number of blocks to keep in the db.
100    ///
101    /// NOTE: only finalized blocks are subject for removal!
102    pub blocks_pruning: BlocksPruning,
103    /// RPC configuration
104    pub rpc_options: SubstrateRpcConfiguration,
105    /// IP and port (TCP) to start Prometheus exporter on
106    pub prometheus_listen_on: Option<SocketAddr>,
107    /// Telemetry service URL. `None` if disabled.
108    pub telemetry_endpoints: Option<TelemetryEndpoints>,
109    /// Enable authoring even when offline
110    pub force_authoring: bool,
111    /// Chain specification
112    pub chain_spec: Box<dyn ChainSpec>,
113    /// Executor configuration
114    pub executor: ExecutorConfiguration,
115    /// Trie cache size
116    pub trie_cache_size: Option<usize>,
117}
118
119impl From<SubstrateConfiguration> for Configuration {
120    fn from(configuration: SubstrateConfiguration) -> Self {
121        let default_peers_set_num_full = configuration.network.default_peers_set.in_peers
122            + configuration.network.default_peers_set.out_peers;
123        let client_version = format!("{}/{}", configuration.impl_name, configuration.impl_version);
124
125        let rpc_batch_config = if configuration.rpc_options.disable_batch_requests {
126            RpcBatchRequestConfig::Disabled
127        } else if let Some(l) = configuration.rpc_options.max_batch_request_len {
128            RpcBatchRequestConfig::Limit(l)
129        } else {
130            RpcBatchRequestConfig::Unlimited
131        };
132        let rpc_addr = configuration.rpc_options.listen_on.map(|listen_addr| {
133            vec![RpcEndpoint {
134                batch_config: rpc_batch_config,
135                max_connections: configuration.rpc_options.max_connections,
136                listen_addr,
137                rpc_methods: configuration.rpc_options.methods,
138                rate_limit: configuration.rpc_options.rate_limit,
139                rate_limit_trust_proxy_headers: configuration
140                    .rpc_options
141                    .rate_limit_trust_proxy_headers,
142                rate_limit_whitelisted_ips: configuration
143                    .rpc_options
144                    .rate_limit_whitelisted_ips
145                    .clone(),
146                max_payload_in_mb: RPC_DEFAULT_MAX_REQUEST_SIZE_MB,
147                max_payload_out_mb: RPC_DEFAULT_MAX_RESPONSE_SIZE_MB,
148                max_subscriptions_per_connection: configuration
149                    .rpc_options
150                    .max_subscriptions_per_connection,
151                max_buffer_capacity_per_connection: configuration
152                    .rpc_options
153                    .message_buffer_capacity_per_connection,
154                cors: configuration.rpc_options.cors.clone(),
155                retry_random_port: true,
156                is_optional: false,
157            }]
158        });
159
160        Self {
161            impl_name: configuration.impl_name,
162            impl_version: configuration.impl_version,
163            tokio_handle: Handle::current(),
164            transaction_pool: configuration.transaction_pool,
165            network: NetworkConfiguration {
166                net_config_path: None,
167                listen_addresses: configuration.network.listen_on,
168                public_addresses: configuration.network.public_addresses,
169                boot_nodes: if !configuration.network.bootstrap_nodes.is_empty() {
170                    configuration.network.bootstrap_nodes
171                } else {
172                    configuration.chain_spec.boot_nodes().to_vec()
173                },
174                node_key: configuration.network.node_key,
175                default_peers_set: configuration.network.default_peers_set,
176                default_peers_set_num_full,
177                client_version,
178                node_name: configuration.network.node_name,
179                transport: TransportConfig::Normal {
180                    enable_mdns: false,
181                    allow_private_ip: configuration.network.allow_private_ips,
182                },
183                // Substrate's default
184                max_parallel_downloads: 5,
185                // Substrate's default
186                max_blocks_per_request: 64,
187                // Substrate's default, full mode
188                sync_mode: SyncMode::Full,
189                // Disable syncing engine because domain blocks are only created from local
190                // consensus blocks, not synced blocks from remote peers.
191                pause_sync: Arc::new(AtomicBool::new(true)),
192                // Substrate's default
193                enable_dht_random_walk: true,
194                // Substrate's default
195                allow_non_globals_in_dht: configuration.network.allow_private_ips,
196                // Substrate's default
197                kademlia_disjoint_query_paths: false,
198                kademlia_replication_factor: NonZeroUsize::new(DEFAULT_KADEMLIA_REPLICATION_FACTOR)
199                    .expect("value is a constant; constant is non-zero; qed"),
200                ipfs_server: false,
201                yamux_window_size: None,
202                network_backend: NetworkBackendType::Libp2p,
203                force_synced: configuration.network.force_synced,
204            },
205            // Not used on consensus chain
206            keystore: configuration.keystore,
207            database: DatabaseSource::ParityDb {
208                path: configuration.base_path.join("db"),
209            },
210            data_path: configuration.base_path.clone(),
211            trie_cache_maximum_size: configuration.trie_cache_size,
212            state_pruning: Some(configuration.state_pruning),
213            blocks_pruning: configuration.blocks_pruning,
214            executor: configuration.executor,
215            wasm_runtime_overrides: None,
216            rpc: RpcConfiguration {
217                addr: rpc_addr,
218                methods: configuration.rpc_options.methods,
219                max_connections: configuration.rpc_options.max_connections,
220                cors: configuration.rpc_options.cors,
221                max_request_size: RPC_DEFAULT_MAX_REQUEST_SIZE_MB,
222                max_response_size: RPC_DEFAULT_MAX_RESPONSE_SIZE_MB,
223                id_provider: None,
224                max_subs_per_conn: configuration.rpc_options.max_subscriptions_per_connection,
225                // Doesn't matter since we have specified address above
226                port: 0,
227                message_buffer_capacity: configuration
228                    .rpc_options
229                    .message_buffer_capacity_per_connection,
230                batch_config: rpc_batch_config,
231                rate_limit: configuration.rpc_options.rate_limit,
232                rate_limit_whitelisted_ips: configuration.rpc_options.rate_limit_whitelisted_ips,
233                rate_limit_trust_proxy_headers: configuration
234                    .rpc_options
235                    .rate_limit_trust_proxy_headers,
236            },
237            prometheus_config: configuration
238                .prometheus_listen_on
239                .map(|prometheus_listen_on| {
240                    PrometheusConfig::new_with_default_registry(
241                        prometheus_listen_on,
242                        configuration.chain_spec.id().to_string(),
243                    )
244                }),
245            telemetry_endpoints: configuration.telemetry_endpoints,
246            // Offchain worker is not used in Subspace
247            offchain_worker: OffchainWorkerConfig {
248                enabled: false,
249                indexing_enabled: false,
250            },
251            force_authoring: configuration.force_authoring,
252            disable_grandpa: true,
253            dev_key_seed: None,
254            tracing_targets: None,
255            tracing_receiver: Default::default(),
256            chain_spec: configuration.chain_spec,
257            // Substrate's default
258            announce_block: true,
259            role: if configuration.operator {
260                sc_service::Role::Authority
261            } else {
262                sc_service::Role::Full
263            },
264            base_path: BasePath::new(configuration.base_path),
265        }
266    }
267}