1use crate::ProtocolVersion;
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13pub struct ProtocolVariant {
14 pub version: ProtocolVersion,
15 pub name: String,
16 pub description: String,
17 pub is_production: bool,
18 pub supports_mining: bool,
19 pub supports_wallet: bool,
20}
21
22impl ProtocolVariant {
23 pub fn all_variants() -> Vec<Self> {
25 vec![
26 ProtocolVariant {
27 version: ProtocolVersion::BitcoinV1,
28 name: "Bitcoin Mainnet".to_string(),
29 description: "Production Bitcoin network with full consensus rules".to_string(),
30 is_production: true,
31 supports_mining: true,
32 supports_wallet: true,
33 },
34 ProtocolVariant {
35 version: ProtocolVersion::Testnet3,
36 name: "Bitcoin Testnet".to_string(),
37 description: "Bitcoin test network for development and testing".to_string(),
38 is_production: false,
39 supports_mining: true,
40 supports_wallet: true,
41 },
42 ProtocolVariant {
43 version: ProtocolVersion::Regtest,
44 name: "Bitcoin Regtest".to_string(),
45 description: "Regression testing network with configurable difficulty".to_string(),
46 is_production: false,
47 supports_mining: true,
48 supports_wallet: true,
49 },
50 ]
51 }
52
53 pub fn for_version(version: ProtocolVersion) -> Option<Self> {
55 Self::all_variants()
56 .into_iter()
57 .find(|v| v.version == version)
58 }
59
60 pub fn is_production_ready(&self) -> bool {
62 self.is_production
63 }
64
65 pub fn supports_mining_operations(&self) -> bool {
67 self.supports_mining
68 }
69
70 pub fn supports_wallet_operations(&self) -> bool {
72 self.supports_wallet
73 }
74}
75
76#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
78pub struct ProtocolEvolution {
79 pub version: u32,
81 pub enabled_features: Vec<String>,
83 pub deprecated_features: Vec<String>,
85 pub breaking_changes: Vec<String>,
87}
88
89impl ProtocolEvolution {
90 pub fn bitcoin_v1() -> Self {
92 Self {
93 version: 1,
94 enabled_features: vec![
95 "basic_transactions".to_string(),
96 "proof_of_work".to_string(),
97 "economic_model".to_string(),
98 "p2p_networking".to_string(),
99 ],
100 deprecated_features: vec![],
101 breaking_changes: vec![],
102 }
103 }
104
105 pub fn bitcoin_v2() -> Self {
107 Self {
108 version: 2,
109 enabled_features: vec![
110 "basic_transactions".to_string(),
111 "proof_of_work".to_string(),
112 "economic_model".to_string(),
113 "p2p_networking".to_string(),
114 "advanced_scripting".to_string(),
115 "privacy_features".to_string(),
116 ],
117 deprecated_features: vec!["legacy_addresses".to_string()],
118 breaking_changes: vec![
119 "new_address_format".to_string(),
120 "enhanced_script_engine".to_string(),
121 ],
122 }
123 }
124
125 pub fn has_feature(&self, feature: &str) -> bool {
127 self.enabled_features.contains(&feature.to_string())
128 }
129
130 pub fn is_deprecated(&self, feature: &str) -> bool {
132 self.deprecated_features.contains(&feature.to_string())
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 use super::*;
139
140 #[test]
141 fn test_protocol_variants() {
142 let variants = ProtocolVariant::all_variants();
143 assert_eq!(variants.len(), 3);
144
145 let mainnet = ProtocolVariant::for_version(ProtocolVersion::BitcoinV1).unwrap();
146 assert_eq!(mainnet.name, "Bitcoin Mainnet");
147 assert!(mainnet.is_production_ready());
148 assert!(mainnet.supports_mining_operations());
149
150 let regtest = ProtocolVariant::for_version(ProtocolVersion::Regtest).unwrap();
151 assert_eq!(regtest.name, "Bitcoin Regtest");
152 assert!(!regtest.is_production_ready());
153 assert!(regtest.supports_mining_operations());
154 }
155
156 #[test]
157 fn test_protocol_variants_all_versions() {
158 let variants = ProtocolVariant::all_variants();
159
160 let mainnet = variants
162 .iter()
163 .find(|v| v.version == ProtocolVersion::BitcoinV1)
164 .unwrap();
165 let testnet = variants
166 .iter()
167 .find(|v| v.version == ProtocolVersion::Testnet3)
168 .unwrap();
169 let regtest = variants
170 .iter()
171 .find(|v| v.version == ProtocolVersion::Regtest)
172 .unwrap();
173
174 assert_eq!(mainnet.name, "Bitcoin Mainnet");
175 assert_eq!(testnet.name, "Bitcoin Testnet");
176 assert_eq!(regtest.name, "Bitcoin Regtest");
177 }
178
179 #[test]
180 fn test_protocol_variant_lookup() {
181 let mainnet = ProtocolVariant::for_version(ProtocolVersion::BitcoinV1).unwrap();
183 let testnet = ProtocolVariant::for_version(ProtocolVersion::Testnet3).unwrap();
184 let regtest = ProtocolVariant::for_version(ProtocolVersion::Regtest).unwrap();
185
186 assert_eq!(mainnet.version, ProtocolVersion::BitcoinV1);
187 assert_eq!(testnet.version, ProtocolVersion::Testnet3);
188 assert_eq!(regtest.version, ProtocolVersion::Regtest);
189 }
190
191 #[test]
192 fn test_protocol_variant_production_readiness() {
193 let mainnet = ProtocolVariant::for_version(ProtocolVersion::BitcoinV1).unwrap();
194 let testnet = ProtocolVariant::for_version(ProtocolVersion::Testnet3).unwrap();
195 let regtest = ProtocolVariant::for_version(ProtocolVersion::Regtest).unwrap();
196
197 assert!(mainnet.is_production_ready());
198 assert!(!testnet.is_production_ready());
199 assert!(!regtest.is_production_ready());
200 }
201
202 #[test]
203 fn test_protocol_variant_mining_support() {
204 let mainnet = ProtocolVariant::for_version(ProtocolVersion::BitcoinV1).unwrap();
205 let testnet = ProtocolVariant::for_version(ProtocolVersion::Testnet3).unwrap();
206 let regtest = ProtocolVariant::for_version(ProtocolVersion::Regtest).unwrap();
207
208 assert!(mainnet.supports_mining_operations());
209 assert!(testnet.supports_mining_operations());
210 assert!(regtest.supports_mining_operations());
211 }
212
213 #[test]
214 fn test_protocol_variant_wallet_support() {
215 let mainnet = ProtocolVariant::for_version(ProtocolVersion::BitcoinV1).unwrap();
216 let testnet = ProtocolVariant::for_version(ProtocolVersion::Testnet3).unwrap();
217 let regtest = ProtocolVariant::for_version(ProtocolVersion::Regtest).unwrap();
218
219 assert!(mainnet.supports_wallet_operations());
220 assert!(testnet.supports_wallet_operations());
221 assert!(regtest.supports_wallet_operations());
222 }
223
224 #[test]
225 fn test_protocol_variant_descriptions() {
226 let mainnet = ProtocolVariant::for_version(ProtocolVersion::BitcoinV1).unwrap();
227 let testnet = ProtocolVariant::for_version(ProtocolVersion::Testnet3).unwrap();
228 let regtest = ProtocolVariant::for_version(ProtocolVersion::Regtest).unwrap();
229
230 assert!(mainnet.description.contains("Production"));
231 assert!(testnet.description.contains("test"));
232 assert!(regtest.description.contains("testing"));
233 }
234
235 #[test]
236 fn test_protocol_variant_serialization() {
237 let mainnet = ProtocolVariant::for_version(ProtocolVersion::BitcoinV1).unwrap();
238 let json = serde_json::to_string(&mainnet).unwrap();
239 let deserialized: ProtocolVariant = serde_json::from_str(&json).unwrap();
240
241 assert_eq!(mainnet.version, deserialized.version);
242 assert_eq!(mainnet.name, deserialized.name);
243 assert_eq!(mainnet.description, deserialized.description);
244 assert_eq!(mainnet.is_production, deserialized.is_production);
245 assert_eq!(mainnet.supports_mining, deserialized.supports_mining);
246 assert_eq!(mainnet.supports_wallet, deserialized.supports_wallet);
247 }
248
249 #[test]
250 fn test_protocol_variant_equality() {
251 let mainnet1 = ProtocolVariant::for_version(ProtocolVersion::BitcoinV1).unwrap();
252 let mainnet2 = ProtocolVariant::for_version(ProtocolVersion::BitcoinV1).unwrap();
253 let testnet = ProtocolVariant::for_version(ProtocolVersion::Testnet3).unwrap();
254
255 assert_eq!(mainnet1, mainnet2);
256 assert_ne!(mainnet1, testnet);
257 }
258
259 #[test]
260 fn test_protocol_evolution() {
261 let v1 = ProtocolEvolution::bitcoin_v1();
262 assert_eq!(v1.version, 1);
263 assert!(v1.has_feature("basic_transactions"));
264 assert!(!v1.is_deprecated("basic_transactions"));
265
266 let v2 = ProtocolEvolution::bitcoin_v2();
267 assert_eq!(v2.version, 2);
268 assert!(v2.has_feature("privacy_features"));
269 assert!(v2.is_deprecated("legacy_addresses"));
270 }
271
272 #[test]
273 fn test_protocol_evolution_v1_features() {
274 let v1 = ProtocolEvolution::bitcoin_v1();
275
276 assert!(v1.has_feature("basic_transactions"));
278 assert!(v1.has_feature("proof_of_work"));
279 assert!(v1.has_feature("economic_model"));
280 assert!(v1.has_feature("p2p_networking"));
281
282 assert!(!v1.has_feature("advanced_scripting"));
284 assert!(!v1.has_feature("privacy_features"));
285
286 assert!(!v1.is_deprecated("basic_transactions"));
288 assert!(!v1.is_deprecated("proof_of_work"));
289 }
290
291 #[test]
292 fn test_protocol_evolution_v2_features() {
293 let v2 = ProtocolEvolution::bitcoin_v2();
294
295 assert!(v2.has_feature("basic_transactions"));
297 assert!(v2.has_feature("proof_of_work"));
298 assert!(v2.has_feature("economic_model"));
299 assert!(v2.has_feature("p2p_networking"));
300
301 assert!(v2.has_feature("advanced_scripting"));
303 assert!(v2.has_feature("privacy_features"));
304
305 assert!(v2.is_deprecated("legacy_addresses"));
307
308 assert!(v2
310 .breaking_changes
311 .contains(&"new_address_format".to_string()));
312 assert!(v2
313 .breaking_changes
314 .contains(&"enhanced_script_engine".to_string()));
315 }
316
317 #[test]
318 fn test_protocol_evolution_feature_queries() {
319 let v1 = ProtocolEvolution::bitcoin_v1();
320 let v2 = ProtocolEvolution::bitcoin_v2();
321
322 assert!(v1.has_feature("basic_transactions"));
324 assert!(!v1.has_feature("nonexistent"));
325 assert!(!v1.has_feature(""));
326
327 assert!(!v1.is_deprecated("basic_transactions"));
329 assert!(v2.is_deprecated("legacy_addresses"));
330 assert!(!v2.is_deprecated("basic_transactions"));
331 }
332
333 #[test]
334 fn test_protocol_evolution_serialization() {
335 let v1 = ProtocolEvolution::bitcoin_v1();
336 let json = serde_json::to_string(&v1).unwrap();
337 let deserialized: ProtocolEvolution = serde_json::from_str(&json).unwrap();
338
339 assert_eq!(v1.version, deserialized.version);
340 assert_eq!(v1.enabled_features, deserialized.enabled_features);
341 assert_eq!(v1.deprecated_features, deserialized.deprecated_features);
342 assert_eq!(v1.breaking_changes, deserialized.breaking_changes);
343 }
344
345 #[test]
346 fn test_protocol_evolution_equality() {
347 let v1_1 = ProtocolEvolution::bitcoin_v1();
348 let v1_2 = ProtocolEvolution::bitcoin_v1();
349 let v2 = ProtocolEvolution::bitcoin_v2();
350
351 assert_eq!(v1_1, v1_2);
352 assert_ne!(v1_1, v2);
353 }
354
355 #[test]
356 fn test_protocol_evolution_version_comparison() {
357 let v1 = ProtocolEvolution::bitcoin_v1();
358 let v2 = ProtocolEvolution::bitcoin_v2();
359
360 assert!(v2.version > v1.version);
361 assert_eq!(v1.version, 1);
362 assert_eq!(v2.version, 2);
363 }
364
365 #[test]
366 fn test_protocol_evolution_feature_sets() {
367 let v1 = ProtocolEvolution::bitcoin_v1();
368 let v2 = ProtocolEvolution::bitcoin_v2();
369
370 for feature in &v1.enabled_features {
372 assert!(v2.has_feature(feature));
373 }
374
375 assert!(v2.enabled_features.len() > v1.enabled_features.len());
377
378 assert!(v1.deprecated_features.is_empty());
380
381 assert!(!v2.deprecated_features.is_empty());
383 }
384}