348 lines
15 KiB
Rust

use std::{
collections::HashSet,
num::{NonZeroU64, NonZeroUsize},
path::PathBuf,
time::Duration,
};
use chain_leader::LeaderConfig as ChainLeaderConfig;
use chain_network::{BootstrapConfig as ChainBootstrapConfig, OrphanConfig, SyncConfig};
use chain_service::StartingState;
use key_management_system_service::keys::{Key, ZkKey};
use nomos_blend_service::{
core::settings::{CoverTrafficSettings, MessageDelayerSettings, SchedulerSettings, ZkSettings},
settings::TimingSettings,
};
use nomos_da_network_core::{
protocols::sampling::SubnetsConfig, swarm::DAConnectionPolicySettings,
};
use nomos_da_network_service::{
NetworkConfig as DaNetworkConfig, api::http::ApiAdapterSettings,
backends::libp2p::common::DaNetworkBackendSettings,
};
use nomos_da_sampling::{
DaSamplingServiceSettings, backend::kzgrs::KzgrsSamplingBackendSettings,
verifier::kzgrs::KzgrsDaVerifierSettings as SamplingVerifierSettings,
};
use nomos_da_verifier::{
DaVerifierServiceSettings,
backend::{kzgrs::KzgrsDaVerifierSettings, trigger::MempoolPublishTriggerConfig},
storage::adapters::rocksdb::RocksAdapterSettings as VerifierStorageAdapterSettings,
};
use nomos_node::{
Config as ValidatorConfig, RocksBackendSettings,
api::backend::AxumBackendSettings as NodeAxumBackendSettings,
config::{
blend::{
deployment::{self as blend_deployment},
serde as blend_serde,
},
cryptarchia::{
deployment::{
SdpConfig as DeploymentSdpConfig, Settings as CryptarchiaDeploymentSettings,
},
serde::{
Config as CryptarchiaConfig, LeaderConfig as CryptarchiaLeaderConfig,
NetworkConfig as CryptarchiaNetworkConfig,
ServiceConfig as CryptarchiaServiceConfig,
},
},
deployment::DeploymentSettings,
mempool::{
deployment::Settings as MempoolDeploymentSettings, serde::Config as MempoolConfig,
},
network::deployment::Settings as NetworkDeploymentSettings,
time::{deployment::Settings as TimeDeploymentSettings, serde::Config as TimeConfig},
},
};
use nomos_sdp::SdpSettings;
use nomos_time::backends::{NtpTimeBackendSettings, ntp::async_client::NTPClientSettings};
use nomos_utils::math::NonNegativeF64;
use nomos_wallet::WalletServiceSettings;
use crate::{
adjust_timeout,
common::kms::key_id_for_preload_backend,
topology::configs::{
GeneralConfig, blend::GeneralBlendConfig as TopologyBlendConfig, wallet::WalletAccount,
},
};
#[must_use]
#[expect(
clippy::too_many_lines,
reason = "Validator config wiring aggregates many service settings"
)]
pub fn create_validator_config(config: GeneralConfig) -> ValidatorConfig {
let da_policy_settings = config.da_config.policy_settings;
let (blend_user_config, blend_deployment, network_deployment) =
build_blend_service_config(&config.blend_config);
let cryptarchia_deployment = CryptarchiaDeploymentSettings {
epoch_config: config.consensus_config.ledger_config.epoch_config,
consensus_config: config.consensus_config.ledger_config.consensus_config,
sdp_config: DeploymentSdpConfig {
service_params: config
.consensus_config
.ledger_config
.sdp_config
.service_params
.clone(),
min_stake: config.consensus_config.ledger_config.sdp_config.min_stake,
},
gossipsub_protocol: "/cryptarchia/proto".to_owned(),
};
let time_deployment = TimeDeploymentSettings {
slot_duration: config.time_config.slot_duration,
};
let mempool_deployment = MempoolDeploymentSettings {
pubsub_topic: "mantle".to_owned(),
};
let deployment_settings = DeploymentSettings::new_custom(
blend_deployment,
network_deployment,
cryptarchia_deployment,
time_deployment,
mempool_deployment,
);
ValidatorConfig {
network: config.network_config,
blend: blend_user_config,
deployment: deployment_settings,
cryptarchia: CryptarchiaConfig {
service: CryptarchiaServiceConfig {
starting_state: StartingState::Genesis {
genesis_tx: config.consensus_config.genesis_tx,
},
// Disable on-disk recovery in compose tests to avoid serde errors on
// non-string keys and keep services alive.
recovery_file: PathBuf::new(),
bootstrap: chain_service::BootstrapConfig {
prolonged_bootstrap_period: config
.bootstrapping_config
.prolonged_bootstrap_period,
force_bootstrap: false,
offline_grace_period: chain_service::OfflineGracePeriodConfig {
grace_period: Duration::from_secs(20 * 60),
state_recording_interval: Duration::from_secs(60),
},
},
},
network: CryptarchiaNetworkConfig {
bootstrap: ChainBootstrapConfig {
ibd: chain_network::IbdConfig {
peers: HashSet::new(),
delay_before_new_download: Duration::from_secs(10),
},
},
sync: SyncConfig {
orphan: OrphanConfig {
max_orphan_cache_size: NonZeroUsize::new(5)
.expect("Max orphan cache size must be non-zero"),
},
},
},
leader: CryptarchiaLeaderConfig {
leader: ChainLeaderConfig {
pk: config.consensus_config.leader_config.pk,
sk: config.consensus_config.leader_config.sk.clone(),
},
},
},
da_network: DaNetworkConfig {
backend: DaNetworkBackendSettings {
node_key: config.da_config.node_key,
listening_address: config.da_config.listening_address,
policy_settings: DAConnectionPolicySettings {
min_dispersal_peers: 0,
min_replication_peers: da_policy_settings.min_replication_peers,
max_dispersal_failures: da_policy_settings.max_dispersal_failures,
max_sampling_failures: da_policy_settings.max_sampling_failures,
max_replication_failures: da_policy_settings.max_replication_failures,
malicious_threshold: da_policy_settings.malicious_threshold,
},
monitor_settings: config.da_config.monitor_settings,
balancer_interval: config.da_config.balancer_interval,
redial_cooldown: config.da_config.redial_cooldown,
replication_settings: config.da_config.replication_settings,
subnets_settings: SubnetsConfig {
num_of_subnets: config.da_config.num_samples as usize,
shares_retry_limit: config.da_config.retry_shares_limit,
commitments_retry_limit: config.da_config.retry_commitments_limit,
},
},
membership: config.da_config.membership.clone(),
api_adapter_settings: ApiAdapterSettings {
api_port: config.api_config.address.port(),
is_secure: false,
},
subnet_refresh_interval: config.da_config.subnets_refresh_interval,
subnet_threshold: config.da_config.num_samples as usize,
min_session_members: config.da_config.num_samples as usize,
},
da_verifier: DaVerifierServiceSettings {
share_verifier_settings: KzgrsDaVerifierSettings {
global_params_path: config.da_config.global_params_path.clone(),
domain_size: config.da_config.num_subnets as usize,
},
tx_verifier_settings: (),
network_adapter_settings: (),
storage_adapter_settings: VerifierStorageAdapterSettings {
blob_storage_directory: "./".into(),
},
mempool_trigger_settings: MempoolPublishTriggerConfig {
publish_threshold: NonNegativeF64::try_from(0.8).unwrap(),
share_duration: Duration::from_secs(5),
prune_duration: Duration::from_secs(30),
prune_interval: Duration::from_secs(5),
},
},
tracing: config.tracing_config.tracing_settings,
http: nomos_api::ApiServiceSettings {
backend_settings: NodeAxumBackendSettings {
address: config.api_config.address,
rate_limit_per_second: 10000,
rate_limit_burst: 10000,
max_concurrent_requests: 1000,
..Default::default()
},
},
da_sampling: DaSamplingServiceSettings {
sampling_settings: KzgrsSamplingBackendSettings {
num_samples: config.da_config.num_samples,
num_subnets: config.da_config.num_subnets,
old_blobs_check_interval: config.da_config.old_blobs_check_interval,
blobs_validity_duration: config.da_config.blobs_validity_duration,
},
share_verifier_settings: SamplingVerifierSettings {
global_params_path: config.da_config.global_params_path,
domain_size: config.da_config.num_subnets as usize,
},
commitments_wait_duration: Duration::from_secs(1),
sdp_blob_trigger_sampling_delay: adjust_timeout(Duration::from_secs(5)),
},
storage: RocksBackendSettings {
db_path: "./db".into(),
read_only: false,
column_family: Some("blocks".into()),
},
time: TimeConfig {
backend: NtpTimeBackendSettings {
ntp_server: config.time_config.ntp_server,
ntp_client_settings: NTPClientSettings {
timeout: config.time_config.timeout,
listening_interface: config.time_config.interface,
},
update_interval: config.time_config.update_interval,
},
chain_start_time: config.time_config.chain_start_time,
},
mempool: MempoolConfig {
recovery_path: "./recovery/mempool.json".into(),
},
sdp: SdpSettings { declaration: None },
wallet: WalletServiceSettings {
known_keys: {
let mut keys = HashSet::from_iter([config.consensus_config.leader_config.pk]);
keys.extend(
config
.consensus_config
.wallet_accounts
.iter()
.map(WalletAccount::public_key),
);
keys
},
},
key_management: config.kms_config,
testing_http: nomos_api::ApiServiceSettings {
backend_settings: NodeAxumBackendSettings {
address: config.api_config.testing_http_address,
rate_limit_per_second: 10000,
rate_limit_burst: 10000,
max_concurrent_requests: 1000,
..Default::default()
},
},
}
}
fn build_blend_service_config(
config: &TopologyBlendConfig,
) -> (
blend_serde::Config,
blend_deployment::Settings,
NetworkDeploymentSettings,
) {
let zk_key_id =
key_id_for_preload_backend(&Key::from(ZkKey::new(config.secret_zk_key.clone())));
let backend_core = &config.backend_core;
let backend_edge = &config.backend_edge;
let user = blend_serde::Config {
common: blend_serde::common::Config {
non_ephemeral_signing_key: config.private_key.clone(),
recovery_path_prefix: PathBuf::from("./recovery/blend"),
},
core: blend_serde::core::Config {
backend: blend_serde::core::BackendConfig {
listening_address: backend_core.listening_address.clone(),
core_peering_degree: backend_core.core_peering_degree.clone(),
edge_node_connection_timeout: backend_core.edge_node_connection_timeout,
max_edge_node_incoming_connections: backend_core.max_edge_node_incoming_connections,
max_dial_attempts_per_peer: backend_core.max_dial_attempts_per_peer,
},
zk: ZkSettings {
secret_key_kms_id: zk_key_id,
},
},
edge: blend_serde::edge::Config {
backend: blend_serde::edge::BackendConfig {
max_dial_attempts_per_peer_per_message: backend_edge
.max_dial_attempts_per_peer_per_message,
replication_factor: backend_edge.replication_factor,
},
},
};
let deployment_settings = blend_deployment::Settings {
common: blend_deployment::CommonSettings {
num_blend_layers: NonZeroU64::try_from(1).unwrap(),
minimum_network_size: NonZeroU64::try_from(1).unwrap(),
timing: TimingSettings {
round_duration: Duration::from_secs(1),
rounds_per_interval: NonZeroU64::try_from(30u64).unwrap(),
rounds_per_session: NonZeroU64::try_from(648_000u64).unwrap(),
rounds_per_observation_window: NonZeroU64::try_from(30u64).unwrap(),
rounds_per_session_transition_period: NonZeroU64::try_from(30u64).unwrap(),
epoch_transition_period_in_slots: NonZeroU64::try_from(2_600).unwrap(),
},
protocol_name: backend_core.protocol_name.clone(),
},
core: blend_deployment::CoreSettings {
scheduler: SchedulerSettings {
cover: CoverTrafficSettings {
intervals_for_safety_buffer: 100,
message_frequency_per_round: NonNegativeF64::try_from(1f64).unwrap(),
},
delayer: MessageDelayerSettings {
maximum_release_delay_in_rounds: NonZeroU64::try_from(3u64).unwrap(),
},
},
minimum_messages_coefficient: backend_core.minimum_messages_coefficient,
normalization_constant: backend_core.normalization_constant,
},
};
let network_deployment = NetworkDeploymentSettings {
identify_protocol_name: nomos_libp2p::protocol_name::StreamProtocol::new(
"/integration/nomos/identify/1.0.0",
),
kademlia_protocol_name: nomos_libp2p::protocol_name::StreamProtocol::new(
"/integration/nomos/kad/1.0.0",
),
};
(user, deployment_settings, network_deployment)
}