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 {
124 fn default() -> Self {
125 Self {
126 sync_mode: SyncMode::PeerConsensus,
127 verification_level: VerificationLevel::Standard,
128 consensus: ConsensusConfigSerializable {
129 min_peers: 5,
130 target_peers: 10,
131 consensus_threshold: 0.8,
132 max_peers_per_asn: 2,
133 safety_margin: 2016,
134 shuffle_peers: true,
135 },
136 spam_filter: crate::spam_filter::SpamFilterConfigSerializable::default(),
137 storage: StorageConfig::default(),
138 }
139 }
140}
141
142impl UtxoCommitmentsConfig {
143 pub fn from_json_file(path: &std::path::Path) -> Result<Self, String> {
145 let content = std::fs::read_to_string(path)
146 .map_err(|e| format!("Failed to read config file: {}", e))?;
147
148 serde_json::from_str(&content).map_err(|e| format!("Failed to parse config JSON: {}", e))
149 }
150
151 pub fn to_json_file(&self, path: &std::path::Path) -> Result<(), String> {
153 let content = serde_json::to_string_pretty(self)
154 .map_err(|e| format!("Failed to serialize config: {}", e))?;
155
156 std::fs::write(path, content).map_err(|e| format!("Failed to write config file: {}", e))
157 }
158
159 pub fn create_default_config_file(path: &std::path::Path) -> Result<(), String> {
161 let default_config = Self::default();
162 default_config.to_json_file(path)
163 }
164
165 #[cfg(feature = "utxo-commitments")]
167 pub fn to_consensus_config(&self) -> ConsensusConfig {
168 self.consensus.clone().into()
169 }
170
171 pub fn to_spam_filter_config(&self) -> SpamFilterConfig {
173 self.spam_filter.clone().into()
174 }
175
176 pub fn validate(&self) -> Result<(), String> {
178 if self.consensus.min_peers == 0 {
180 return Err("min_peers must be > 0".to_string());
181 }
182 if self.consensus.target_peers < self.consensus.min_peers {
183 return Err("target_peers must be >= min_peers".to_string());
184 }
185 if self.consensus.consensus_threshold < 0.0 || self.consensus.consensus_threshold > 1.0 {
186 return Err("consensus_threshold must be between 0.0 and 1.0".to_string());
187 }
188 if self.consensus.max_peers_per_asn == 0 {
189 return Err("max_peers_per_asn must be > 0".to_string());
190 }
191
192 if self.spam_filter.dust_threshold < 0 {
194 return Err("dust_threshold must be >= 0".to_string());
195 }
196 if self.spam_filter.min_output_value < 0 {
197 return Err("min_output_value must be >= 0".to_string());
198 }
199
200 Ok(())
201 }
202}