blvm_protocol/utxo_commitments/
config.rs1use crate::spam_filter::SpamFilterConfig;
10use serde::{Deserialize, Serialize};
11
12#[cfg(feature = "utxo-commitments")]
13use crate::utxo_commitments::peer_consensus::ConsensusConfig;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
17pub enum SyncMode {
18 PeerConsensus,
20 Genesis,
22 Hybrid,
24}
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
28pub enum VerificationLevel {
29 Minimal,
31 Standard,
33 Paranoid,
35}
36
37#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
39pub struct StorageConfig {
40 pub keep_filtered_blocks: bool,
42 pub keep_spam_summary: bool,
44 pub keep_utxo_history: bool,
46 pub filtered_blocks_max_age_days: u32,
48}
49
50impl Default for StorageConfig {
51 fn default() -> Self {
52 Self {
53 keep_filtered_blocks: false,
54 keep_spam_summary: true,
55 keep_utxo_history: false,
56 filtered_blocks_max_age_days: 30,
57 }
58 }
59}
60
61#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
63pub struct UtxoCommitmentsConfig {
64 pub sync_mode: SyncMode,
66 pub verification_level: VerificationLevel,
68 pub consensus: ConsensusConfigSerializable,
70 pub spam_filter: crate::spam_filter::SpamFilterConfigSerializable,
72 pub storage: StorageConfig,
74}
75
76#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
78pub struct ConsensusConfigSerializable {
79 pub min_peers: usize,
80 pub target_peers: usize,
81 pub consensus_threshold: f64,
82 pub max_peers_per_asn: usize,
83 pub safety_margin: u64,
84 #[serde(default = "default_shuffle_peers")]
85 pub shuffle_peers: bool,
86}
87
88fn default_shuffle_peers() -> bool {
89 true
90}
91
92#[cfg(feature = "utxo-commitments")]
93impl From<ConsensusConfigSerializable> for ConsensusConfig {
94 fn from(serializable: ConsensusConfigSerializable) -> Self {
95 ConsensusConfig {
96 min_peers: serializable.min_peers,
97 target_peers: serializable.target_peers,
98 consensus_threshold: serializable.consensus_threshold,
99 max_peers_per_asn: serializable.max_peers_per_asn,
100 safety_margin: serializable.safety_margin,
101 shuffle_peers: serializable.shuffle_peers,
102 }
103 }
104}
105
106#[cfg(feature = "utxo-commitments")]
107impl From<ConsensusConfig> for ConsensusConfigSerializable {
108 fn from(config: ConsensusConfig) -> Self {
109 ConsensusConfigSerializable {
110 min_peers: config.min_peers,
111 target_peers: config.target_peers,
112 consensus_threshold: config.consensus_threshold,
113 max_peers_per_asn: config.max_peers_per_asn,
114 safety_margin: config.safety_margin,
115 shuffle_peers: config.shuffle_peers,
116 }
117 }
118}
119
120impl Default for UtxoCommitmentsConfig {
123 fn default() -> Self {
124 Self {
125 sync_mode: SyncMode::PeerConsensus,
126 verification_level: VerificationLevel::Standard,
127 consensus: ConsensusConfigSerializable {
128 min_peers: 5,
129 target_peers: 10,
130 consensus_threshold: 0.8,
131 max_peers_per_asn: 2,
132 safety_margin: 2016,
133 shuffle_peers: true,
134 },
135 spam_filter: crate::spam_filter::SpamFilterConfigSerializable::default(),
136 storage: StorageConfig::default(),
137 }
138 }
139}
140
141impl UtxoCommitmentsConfig {
142 pub fn from_json_file(path: &std::path::Path) -> Result<Self, String> {
144 let content = std::fs::read_to_string(path)
145 .map_err(|e| format!("Failed to read config file: {e}"))?;
146
147 serde_json::from_str(&content).map_err(|e| format!("Failed to parse config JSON: {e}"))
148 }
149
150 pub fn to_json_file(&self, path: &std::path::Path) -> Result<(), String> {
152 let content = serde_json::to_string_pretty(self)
153 .map_err(|e| format!("Failed to serialize config: {e}"))?;
154
155 std::fs::write(path, content).map_err(|e| format!("Failed to write config file: {e}"))
156 }
157
158 pub fn create_default_config_file(path: &std::path::Path) -> Result<(), String> {
160 let default_config = Self::default();
161 default_config.to_json_file(path)
162 }
163
164 #[cfg(feature = "utxo-commitments")]
166 pub fn to_consensus_config(&self) -> ConsensusConfig {
167 self.consensus.clone().into()
168 }
169
170 pub fn to_spam_filter_config(&self) -> SpamFilterConfig {
172 self.spam_filter.clone().into()
173 }
174
175 pub fn validate(&self) -> Result<(), String> {
177 if self.consensus.min_peers == 0 {
179 return Err("min_peers must be > 0".to_string());
180 }
181 if self.consensus.target_peers < self.consensus.min_peers {
182 return Err("target_peers must be >= min_peers".to_string());
183 }
184 if self.consensus.consensus_threshold < 0.0 || self.consensus.consensus_threshold > 1.0 {
185 return Err("consensus_threshold must be between 0.0 and 1.0".to_string());
186 }
187 if self.consensus.max_peers_per_asn == 0 {
188 return Err("max_peers_per_asn must be > 0".to_string());
189 }
190
191 if self.spam_filter.dust_threshold < 0 {
193 return Err("dust_threshold must be >= 0".to_string());
194 }
195 if self.spam_filter.min_output_value < 0 {
196 return Err("min_output_value must be >= 0".to_string());
197 }
198
199 Ok(())
200 }
201}