use crate::dsn::DsnConfig;
use crate::sync_from_dsn::DsnSyncPieceGetter;
use sc_chain_spec::ChainSpec;
use sc_consensus_subspace::archiver::CreateObjectMappings;
use sc_network::config::{
MultiaddrWithPeerId, NetworkBackendType, NetworkConfiguration, NodeKeyConfig, SetConfig,
SyncMode, TransportConfig, DEFAULT_KADEMLIA_REPLICATION_FACTOR,
};
use sc_service::config::{
ExecutorConfiguration, IpNetwork, KeystoreConfig, OffchainWorkerConfig, PrometheusConfig,
RpcBatchRequestConfig, RpcConfiguration, RpcEndpoint,
};
use sc_service::{
BasePath, BlocksPruning, Configuration, DatabaseSource, PruningMode, RpcMethods,
TransactionPoolOptions,
};
use sc_telemetry::TelemetryEndpoints;
use std::collections::HashSet;
use std::fmt;
use std::net::SocketAddr;
use std::num::{NonZeroU32, NonZeroUsize};
use std::ops::Deref;
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use subspace_networking::libp2p::Multiaddr;
use subspace_networking::Node;
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 sync_mode: ChainSyncMode,
pub force_synced: bool,
}
#[derive(Debug)]
pub struct SubstrateConfiguration {
pub impl_name: String,
pub impl_version: String,
pub farmer: bool,
pub base_path: PathBuf,
pub transaction_pool: TransactionPoolOptions,
pub network: SubstrateNetworkConfiguration,
pub state_pruning: 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 net_config_path = configuration.base_path.join("network");
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: Some(net_config_path.clone()),
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(false)),
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: KeystoreConfig::InMemory,
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: Some(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: true,
},
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.farmer {
sc_service::Role::Authority
} else {
sc_service::Role::Full
},
base_path: BasePath::new(configuration.base_path),
}
}
}
#[derive(Debug)]
#[allow(clippy::large_enum_variant)]
pub enum SubspaceNetworking {
Reuse {
node: Node,
bootstrap_nodes: Vec<Multiaddr>,
},
Create {
config: DsnConfig,
},
}
#[derive(Debug)]
pub struct SubspaceConfiguration {
pub base: Configuration,
pub force_new_slot_notifications: bool,
pub create_object_mappings: CreateObjectMappings,
pub subspace_networking: SubspaceNetworking,
pub dsn_piece_getter: Option<Arc<dyn DsnSyncPieceGetter + Send + Sync + 'static>>,
pub is_timekeeper: bool,
pub timekeeper_cpu_cores: HashSet<usize>,
pub sync: ChainSyncMode,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ChainSyncMode {
Full,
Snap,
}
impl FromStr for ChainSyncMode {
type Err = String;
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"full" => Ok(Self::Full),
"snap" => Ok(Self::Snap),
_ => Err("Unsupported sync type: use full or snap".to_string()),
}
}
}
impl fmt::Display for ChainSyncMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Full => f.write_str("full"),
Self::Snap => f.write_str("snap"),
}
}
}
impl Default for ChainSyncMode {
fn default() -> Self {
Self::Full
}
}
impl Deref for SubspaceConfiguration {
type Target = Configuration;
fn deref(&self) -> &Self::Target {
&self.base
}
}