use sc_chain_spec::ChainSpec;
use sc_network::config::{
MultiaddrWithPeerId, NetworkBackendType, NetworkConfiguration, NodeKeyConfig, SetConfig,
SyncMode, TransportConfig, DEFAULT_KADEMLIA_REPLICATION_FACTOR,
};
use sc_rpc_server::RpcEndpoint;
use sc_service::config::{
ExecutorConfiguration, IpNetwork, KeystoreConfig, OffchainWorkerConfig, PrometheusConfig,
RpcBatchRequestConfig, RpcConfiguration,
};
use sc_service::{
BasePath, BlocksPruning, Configuration, DatabaseSource, PruningMode, RpcMethods,
TransactionPoolOptions,
};
use sc_telemetry::TelemetryEndpoints;
use std::net::SocketAddr;
use std::num::{NonZeroU32, NonZeroUsize};
use std::path::PathBuf;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use tokio::runtime::Handle;
pub const RPC_DEFAULT_MAX_REQUEST_SIZE_MB: u32 = 15;
pub const RPC_DEFAULT_MAX_RESPONSE_SIZE_MB: u32 = 15;
#[derive(Debug)]
pub struct SubstrateRpcConfiguration {
pub listen_on: Option<SocketAddr>,
pub max_connections: u32,
pub cors: Option<Vec<String>>,
pub methods: RpcMethods,
pub rate_limit: Option<NonZeroU32>,
pub rate_limit_whitelisted_ips: Vec<IpNetwork>,
pub rate_limit_trust_proxy_headers: bool,
pub max_subscriptions_per_connection: u32,
pub message_buffer_capacity_per_connection: u32,
pub disable_batch_requests: bool,
pub max_batch_request_len: Option<u32>,
}
#[derive(Debug)]
pub struct SubstrateNetworkConfiguration {
pub listen_on: Vec<sc_network::Multiaddr>,
pub public_addresses: Vec<sc_network::Multiaddr>,
pub bootstrap_nodes: Vec<MultiaddrWithPeerId>,
pub node_key: NodeKeyConfig,
pub default_peers_set: SetConfig,
pub node_name: String,
pub allow_private_ips: bool,
pub force_synced: bool,
}
#[derive(Debug)]
pub struct SubstrateConfiguration {
pub impl_name: String,
pub impl_version: String,
pub operator: bool,
pub base_path: PathBuf,
pub transaction_pool: TransactionPoolOptions,
pub network: SubstrateNetworkConfiguration,
pub keystore: KeystoreConfig,
pub state_pruning: Option<PruningMode>,
pub blocks_pruning: BlocksPruning,
pub rpc_options: SubstrateRpcConfiguration,
pub prometheus_listen_on: Option<SocketAddr>,
pub telemetry_endpoints: Option<TelemetryEndpoints>,
pub force_authoring: bool,
pub chain_spec: Box<dyn ChainSpec>,
}
impl From<SubstrateConfiguration> for Configuration {
fn from(configuration: SubstrateConfiguration) -> Self {
let default_peers_set_num_full = configuration.network.default_peers_set.in_peers
+ configuration.network.default_peers_set.out_peers;
let client_version = format!("{}/{}", configuration.impl_name, configuration.impl_version);
let rpc_batch_config = if configuration.rpc_options.disable_batch_requests {
RpcBatchRequestConfig::Disabled
} else if let Some(l) = configuration.rpc_options.max_batch_request_len {
RpcBatchRequestConfig::Limit(l)
} else {
RpcBatchRequestConfig::Unlimited
};
let rpc_addr = configuration.rpc_options.listen_on.map(|listen_addr| {
vec![RpcEndpoint {
batch_config: rpc_batch_config,
max_connections: configuration.rpc_options.max_connections,
listen_addr,
rpc_methods: configuration.rpc_options.methods,
rate_limit: configuration.rpc_options.rate_limit,
rate_limit_trust_proxy_headers: configuration
.rpc_options
.rate_limit_trust_proxy_headers,
rate_limit_whitelisted_ips: configuration
.rpc_options
.rate_limit_whitelisted_ips
.clone(),
max_payload_in_mb: RPC_DEFAULT_MAX_REQUEST_SIZE_MB,
max_payload_out_mb: RPC_DEFAULT_MAX_RESPONSE_SIZE_MB,
max_subscriptions_per_connection: configuration
.rpc_options
.max_subscriptions_per_connection,
max_buffer_capacity_per_connection: configuration
.rpc_options
.message_buffer_capacity_per_connection,
cors: configuration.rpc_options.cors.clone(),
retry_random_port: true,
is_optional: false,
}]
});
Self {
impl_name: configuration.impl_name,
impl_version: configuration.impl_version,
tokio_handle: Handle::current(),
transaction_pool: configuration.transaction_pool,
network: NetworkConfiguration {
net_config_path: None,
listen_addresses: configuration.network.listen_on,
public_addresses: configuration.network.public_addresses,
boot_nodes: if !configuration.network.bootstrap_nodes.is_empty() {
configuration.network.bootstrap_nodes
} else {
configuration.chain_spec.boot_nodes().to_vec()
},
node_key: configuration.network.node_key,
default_peers_set: configuration.network.default_peers_set,
default_peers_set_num_full,
client_version,
node_name: configuration.network.node_name,
transport: TransportConfig::Normal {
enable_mdns: false,
allow_private_ip: configuration.network.allow_private_ips,
},
max_parallel_downloads: 5,
max_blocks_per_request: 64,
sync_mode: SyncMode::Full,
pause_sync: Arc::new(AtomicBool::new(true)),
enable_dht_random_walk: true,
allow_non_globals_in_dht: configuration.network.allow_private_ips,
kademlia_disjoint_query_paths: false,
kademlia_replication_factor: NonZeroUsize::new(DEFAULT_KADEMLIA_REPLICATION_FACTOR)
.expect("value is a constant; constant is non-zero; qed"),
ipfs_server: false,
yamux_window_size: None,
network_backend: NetworkBackendType::Libp2p,
force_synced: configuration.network.force_synced,
},
keystore: configuration.keystore,
database: DatabaseSource::ParityDb {
path: configuration.base_path.join("db"),
},
data_path: configuration.base_path.clone(),
trie_cache_maximum_size: Some(64 * 1024 * 1024),
state_pruning: configuration.state_pruning,
blocks_pruning: configuration.blocks_pruning,
executor: ExecutorConfiguration {
wasm_method: Default::default(),
max_runtime_instances: 8,
default_heap_pages: None,
runtime_cache_size: 2,
},
wasm_runtime_overrides: None,
rpc: RpcConfiguration {
addr: rpc_addr,
methods: configuration.rpc_options.methods,
max_connections: configuration.rpc_options.max_connections,
cors: configuration.rpc_options.cors,
max_request_size: RPC_DEFAULT_MAX_REQUEST_SIZE_MB,
max_response_size: RPC_DEFAULT_MAX_RESPONSE_SIZE_MB,
id_provider: None,
max_subs_per_conn: configuration.rpc_options.max_subscriptions_per_connection,
port: 0,
message_buffer_capacity: configuration
.rpc_options
.message_buffer_capacity_per_connection,
batch_config: rpc_batch_config,
rate_limit: configuration.rpc_options.rate_limit,
rate_limit_whitelisted_ips: configuration.rpc_options.rate_limit_whitelisted_ips,
rate_limit_trust_proxy_headers: configuration
.rpc_options
.rate_limit_trust_proxy_headers,
},
prometheus_config: configuration
.prometheus_listen_on
.map(|prometheus_listen_on| {
PrometheusConfig::new_with_default_registry(
prometheus_listen_on,
configuration.chain_spec.id().to_string(),
)
}),
telemetry_endpoints: configuration.telemetry_endpoints,
offchain_worker: OffchainWorkerConfig {
enabled: false,
indexing_enabled: false,
},
force_authoring: configuration.force_authoring,
disable_grandpa: true,
dev_key_seed: None,
tracing_targets: None,
tracing_receiver: Default::default(),
chain_spec: configuration.chain_spec,
announce_block: true,
role: if configuration.operator {
sc_service::Role::Authority
} else {
sc_service::Role::Full
},
base_path: BasePath::new(configuration.base_path),
}
}
}