use crate::spam_filter::SpamFilterConfig;
use serde::{Deserialize, Serialize};
#[cfg(feature = "utxo-commitments")]
use crate::utxo_commitments::peer_consensus::ConsensusConfig;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum SyncMode {
PeerConsensus,
Genesis,
Hybrid,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum VerificationLevel {
Minimal,
Standard,
Paranoid,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct StorageConfig {
pub keep_filtered_blocks: bool,
pub keep_spam_summary: bool,
pub keep_utxo_history: bool,
pub filtered_blocks_max_age_days: u32,
}
impl Default for StorageConfig {
fn default() -> Self {
Self {
keep_filtered_blocks: false,
keep_spam_summary: true,
keep_utxo_history: false,
filtered_blocks_max_age_days: 30,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct UtxoCommitmentsConfig {
pub sync_mode: SyncMode,
pub verification_level: VerificationLevel,
pub consensus: ConsensusConfigSerializable,
pub spam_filter: crate::spam_filter::SpamFilterConfigSerializable,
pub storage: StorageConfig,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ConsensusConfigSerializable {
pub min_peers: usize,
pub target_peers: usize,
pub consensus_threshold: f64,
pub max_peers_per_asn: usize,
pub safety_margin: u64,
#[serde(default = "default_shuffle_peers")]
pub shuffle_peers: bool,
}
fn default_shuffle_peers() -> bool {
true
}
#[cfg(feature = "utxo-commitments")]
impl From<ConsensusConfigSerializable> for ConsensusConfig {
fn from(serializable: ConsensusConfigSerializable) -> Self {
ConsensusConfig {
min_peers: serializable.min_peers,
target_peers: serializable.target_peers,
consensus_threshold: serializable.consensus_threshold,
max_peers_per_asn: serializable.max_peers_per_asn,
safety_margin: serializable.safety_margin,
shuffle_peers: serializable.shuffle_peers,
}
}
}
#[cfg(feature = "utxo-commitments")]
impl From<ConsensusConfig> for ConsensusConfigSerializable {
fn from(config: ConsensusConfig) -> Self {
ConsensusConfigSerializable {
min_peers: config.min_peers,
target_peers: config.target_peers,
consensus_threshold: config.consensus_threshold,
max_peers_per_asn: config.max_peers_per_asn,
safety_margin: config.safety_margin,
shuffle_peers: config.shuffle_peers,
}
}
}
impl Default for UtxoCommitmentsConfig {
fn default() -> Self {
Self {
sync_mode: SyncMode::PeerConsensus,
verification_level: VerificationLevel::Standard,
consensus: ConsensusConfigSerializable {
min_peers: 5,
target_peers: 10,
consensus_threshold: 0.8,
max_peers_per_asn: 2,
safety_margin: 2016,
shuffle_peers: true,
},
spam_filter: crate::spam_filter::SpamFilterConfigSerializable::default(),
storage: StorageConfig::default(),
}
}
}
impl UtxoCommitmentsConfig {
pub fn from_json_file(path: &std::path::Path) -> Result<Self, String> {
let content = std::fs::read_to_string(path)
.map_err(|e| format!("Failed to read config file: {}", e))?;
serde_json::from_str(&content).map_err(|e| format!("Failed to parse config JSON: {}", e))
}
pub fn to_json_file(&self, path: &std::path::Path) -> Result<(), String> {
let content = serde_json::to_string_pretty(self)
.map_err(|e| format!("Failed to serialize config: {}", e))?;
std::fs::write(path, content).map_err(|e| format!("Failed to write config file: {}", e))
}
pub fn create_default_config_file(path: &std::path::Path) -> Result<(), String> {
let default_config = Self::default();
default_config.to_json_file(path)
}
#[cfg(feature = "utxo-commitments")]
pub fn to_consensus_config(&self) -> ConsensusConfig {
self.consensus.clone().into()
}
pub fn to_spam_filter_config(&self) -> SpamFilterConfig {
self.spam_filter.clone().into()
}
pub fn validate(&self) -> Result<(), String> {
if self.consensus.min_peers == 0 {
return Err("min_peers must be > 0".to_string());
}
if self.consensus.target_peers < self.consensus.min_peers {
return Err("target_peers must be >= min_peers".to_string());
}
if self.consensus.consensus_threshold < 0.0 || self.consensus.consensus_threshold > 1.0 {
return Err("consensus_threshold must be between 0.0 and 1.0".to_string());
}
if self.consensus.max_peers_per_asn == 0 {
return Err("max_peers_per_asn must be > 0".to_string());
}
if self.spam_filter.dust_threshold < 0 {
return Err("dust_threshold must be >= 0".to_string());
}
if self.spam_filter.min_output_value < 0 {
return Err("min_output_value must be >= 0".to_string());
}
Ok(())
}
}