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 ProtocolVariant {
51 version: ProtocolVersion::Signet,
52 name: "Bitcoin Signet".to_string(),
53 description: "Signet test network with BIP325 block-solution challenge".to_string(),
54 is_production: false,
55 supports_mining: true,
56 supports_wallet: true,
57 },
58 ]
59 }
60
61 pub fn for_version(version: ProtocolVersion) -> Option<Self> {
63 Self::all_variants()
64 .into_iter()
65 .find(|v| v.version == version)
66 }
67
68 pub fn is_production_ready(&self) -> bool {
70 self.is_production
71 }
72
73 pub fn supports_mining_operations(&self) -> bool {
75 self.supports_mining
76 }
77
78 pub fn supports_wallet_operations(&self) -> bool {
80 self.supports_wallet
81 }
82}
83
84#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
86pub struct ProtocolEvolution {
87 pub version: u32,
89 pub enabled_features: Vec<String>,
91 pub deprecated_features: Vec<String>,
93 pub breaking_changes: Vec<String>,
95}
96
97impl ProtocolEvolution {
98 pub fn bitcoin_v1() -> Self {
100 Self {
101 version: 1,
102 enabled_features: vec![
103 "basic_transactions".to_string(),
104 "proof_of_work".to_string(),
105 "economic_model".to_string(),
106 "p2p_networking".to_string(),
107 ],
108 deprecated_features: vec![],
109 breaking_changes: vec![],
110 }
111 }
112
113 pub fn bitcoin_v2() -> Self {
115 Self {
116 version: 2,
117 enabled_features: vec![
118 "basic_transactions".to_string(),
119 "proof_of_work".to_string(),
120 "economic_model".to_string(),
121 "p2p_networking".to_string(),
122 "advanced_scripting".to_string(),
123 "privacy_features".to_string(),
124 ],
125 deprecated_features: vec!["legacy_addresses".to_string()],
126 breaking_changes: vec![
127 "new_address_format".to_string(),
128 "enhanced_script_engine".to_string(),
129 ],
130 }
131 }
132
133 pub fn has_feature(&self, feature: &str) -> bool {
135 self.enabled_features.contains(&feature.to_string())
136 }
137
138 pub fn is_deprecated(&self, feature: &str) -> bool {
140 self.deprecated_features.contains(&feature.to_string())
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn test_protocol_variants() {
150 let variants = ProtocolVariant::all_variants();
151 assert_eq!(variants.len(), 4);
152
153 let mainnet = ProtocolVariant::for_version(ProtocolVersion::BitcoinV1).unwrap();
154 assert_eq!(mainnet.name, "Bitcoin Mainnet");
155 assert!(mainnet.is_production_ready());
156 assert!(mainnet.supports_mining_operations());
157
158 let signet = ProtocolVariant::for_version(ProtocolVersion::Signet).unwrap();
159 assert_eq!(signet.name, "Bitcoin Signet");
160 assert!(!signet.is_production_ready());
161
162 let regtest = ProtocolVariant::for_version(ProtocolVersion::Regtest).unwrap();
163 assert_eq!(regtest.name, "Bitcoin Regtest");
164 assert!(!regtest.is_production_ready());
165 assert!(regtest.supports_mining_operations());
166 }
167
168 #[test]
169 fn test_protocol_variants_all_versions() {
170 let variants = ProtocolVariant::all_variants();
171
172 let mainnet = variants
174 .iter()
175 .find(|v| v.version == ProtocolVersion::BitcoinV1)
176 .unwrap();
177 let testnet = variants
178 .iter()
179 .find(|v| v.version == ProtocolVersion::Testnet3)
180 .unwrap();
181 let regtest = variants
182 .iter()
183 .find(|v| v.version == ProtocolVersion::Regtest)
184 .unwrap();
185
186 assert_eq!(mainnet.name, "Bitcoin Mainnet");
187 assert_eq!(testnet.name, "Bitcoin Testnet");
188 assert_eq!(regtest.name, "Bitcoin Regtest");
189 }
190
191 #[test]
192 fn test_protocol_variant_lookup() {
193 let mainnet = ProtocolVariant::for_version(ProtocolVersion::BitcoinV1).unwrap();
195 let testnet = ProtocolVariant::for_version(ProtocolVersion::Testnet3).unwrap();
196 let regtest = ProtocolVariant::for_version(ProtocolVersion::Regtest).unwrap();
197
198 assert_eq!(mainnet.version, ProtocolVersion::BitcoinV1);
199 assert_eq!(testnet.version, ProtocolVersion::Testnet3);
200 assert_eq!(regtest.version, ProtocolVersion::Regtest);
201 }
202
203 #[test]
204 fn test_protocol_variant_production_readiness() {
205 let mainnet = ProtocolVariant::for_version(ProtocolVersion::BitcoinV1).unwrap();
206 let testnet = ProtocolVariant::for_version(ProtocolVersion::Testnet3).unwrap();
207 let regtest = ProtocolVariant::for_version(ProtocolVersion::Regtest).unwrap();
208
209 assert!(mainnet.is_production_ready());
210 assert!(!testnet.is_production_ready());
211 assert!(!regtest.is_production_ready());
212 }
213
214 #[test]
215 fn test_protocol_variant_mining_support() {
216 let mainnet = ProtocolVariant::for_version(ProtocolVersion::BitcoinV1).unwrap();
217 let testnet = ProtocolVariant::for_version(ProtocolVersion::Testnet3).unwrap();
218 let regtest = ProtocolVariant::for_version(ProtocolVersion::Regtest).unwrap();
219
220 assert!(mainnet.supports_mining_operations());
221 assert!(testnet.supports_mining_operations());
222 assert!(regtest.supports_mining_operations());
223 }
224
225 #[test]
226 fn test_protocol_variant_wallet_support() {
227 let mainnet = ProtocolVariant::for_version(ProtocolVersion::BitcoinV1).unwrap();
228 let testnet = ProtocolVariant::for_version(ProtocolVersion::Testnet3).unwrap();
229 let regtest = ProtocolVariant::for_version(ProtocolVersion::Regtest).unwrap();
230
231 assert!(mainnet.supports_wallet_operations());
232 assert!(testnet.supports_wallet_operations());
233 assert!(regtest.supports_wallet_operations());
234 }
235
236 #[test]
237 fn test_protocol_variant_descriptions() {
238 let mainnet = ProtocolVariant::for_version(ProtocolVersion::BitcoinV1).unwrap();
239 let testnet = ProtocolVariant::for_version(ProtocolVersion::Testnet3).unwrap();
240 let regtest = ProtocolVariant::for_version(ProtocolVersion::Regtest).unwrap();
241
242 assert!(mainnet.description.contains("Production"));
243 assert!(testnet.description.contains("test"));
244 assert!(regtest.description.contains("testing"));
245 }
246
247 #[test]
248 fn test_protocol_variant_serialization() {
249 let mainnet = ProtocolVariant::for_version(ProtocolVersion::BitcoinV1).unwrap();
250 let json = serde_json::to_string(&mainnet).unwrap();
251 let deserialized: ProtocolVariant = serde_json::from_str(&json).unwrap();
252
253 assert_eq!(mainnet.version, deserialized.version);
254 assert_eq!(mainnet.name, deserialized.name);
255 assert_eq!(mainnet.description, deserialized.description);
256 assert_eq!(mainnet.is_production, deserialized.is_production);
257 assert_eq!(mainnet.supports_mining, deserialized.supports_mining);
258 assert_eq!(mainnet.supports_wallet, deserialized.supports_wallet);
259 }
260
261 #[test]
262 fn test_protocol_variant_equality() {
263 let mainnet1 = ProtocolVariant::for_version(ProtocolVersion::BitcoinV1).unwrap();
264 let mainnet2 = ProtocolVariant::for_version(ProtocolVersion::BitcoinV1).unwrap();
265 let testnet = ProtocolVariant::for_version(ProtocolVersion::Testnet3).unwrap();
266
267 assert_eq!(mainnet1, mainnet2);
268 assert_ne!(mainnet1, testnet);
269 }
270
271 #[test]
272 fn test_protocol_evolution() {
273 let v1 = ProtocolEvolution::bitcoin_v1();
274 assert_eq!(v1.version, 1);
275 assert!(v1.has_feature("basic_transactions"));
276 assert!(!v1.is_deprecated("basic_transactions"));
277
278 let v2 = ProtocolEvolution::bitcoin_v2();
279 assert_eq!(v2.version, 2);
280 assert!(v2.has_feature("privacy_features"));
281 assert!(v2.is_deprecated("legacy_addresses"));
282 }
283
284 #[test]
285 fn test_protocol_evolution_v1_features() {
286 let v1 = ProtocolEvolution::bitcoin_v1();
287
288 assert!(v1.has_feature("basic_transactions"));
290 assert!(v1.has_feature("proof_of_work"));
291 assert!(v1.has_feature("economic_model"));
292 assert!(v1.has_feature("p2p_networking"));
293
294 assert!(!v1.has_feature("advanced_scripting"));
296 assert!(!v1.has_feature("privacy_features"));
297
298 assert!(!v1.is_deprecated("basic_transactions"));
300 assert!(!v1.is_deprecated("proof_of_work"));
301 }
302
303 #[test]
304 fn test_protocol_evolution_v2_features() {
305 let v2 = ProtocolEvolution::bitcoin_v2();
306
307 assert!(v2.has_feature("basic_transactions"));
309 assert!(v2.has_feature("proof_of_work"));
310 assert!(v2.has_feature("economic_model"));
311 assert!(v2.has_feature("p2p_networking"));
312
313 assert!(v2.has_feature("advanced_scripting"));
315 assert!(v2.has_feature("privacy_features"));
316
317 assert!(v2.is_deprecated("legacy_addresses"));
319
320 assert!(
322 v2.breaking_changes
323 .contains(&"new_address_format".to_string())
324 );
325 assert!(
326 v2.breaking_changes
327 .contains(&"enhanced_script_engine".to_string())
328 );
329 }
330
331 #[test]
332 fn test_protocol_evolution_feature_queries() {
333 let v1 = ProtocolEvolution::bitcoin_v1();
334 let v2 = ProtocolEvolution::bitcoin_v2();
335
336 assert!(v1.has_feature("basic_transactions"));
338 assert!(!v1.has_feature("nonexistent"));
339 assert!(!v1.has_feature(""));
340
341 assert!(!v1.is_deprecated("basic_transactions"));
343 assert!(v2.is_deprecated("legacy_addresses"));
344 assert!(!v2.is_deprecated("basic_transactions"));
345 }
346
347 #[test]
348 fn test_protocol_evolution_serialization() {
349 let v1 = ProtocolEvolution::bitcoin_v1();
350 let json = serde_json::to_string(&v1).unwrap();
351 let deserialized: ProtocolEvolution = serde_json::from_str(&json).unwrap();
352
353 assert_eq!(v1.version, deserialized.version);
354 assert_eq!(v1.enabled_features, deserialized.enabled_features);
355 assert_eq!(v1.deprecated_features, deserialized.deprecated_features);
356 assert_eq!(v1.breaking_changes, deserialized.breaking_changes);
357 }
358
359 #[test]
360 fn test_protocol_evolution_equality() {
361 let v1_1 = ProtocolEvolution::bitcoin_v1();
362 let v1_2 = ProtocolEvolution::bitcoin_v1();
363 let v2 = ProtocolEvolution::bitcoin_v2();
364
365 assert_eq!(v1_1, v1_2);
366 assert_ne!(v1_1, v2);
367 }
368
369 #[test]
370 fn test_protocol_evolution_version_comparison() {
371 let v1 = ProtocolEvolution::bitcoin_v1();
372 let v2 = ProtocolEvolution::bitcoin_v2();
373
374 assert!(v2.version > v1.version);
375 assert_eq!(v1.version, 1);
376 assert_eq!(v2.version, 2);
377 }
378
379 #[test]
380 fn test_protocol_evolution_feature_sets() {
381 let v1 = ProtocolEvolution::bitcoin_v1();
382 let v2 = ProtocolEvolution::bitcoin_v2();
383
384 for feature in &v1.enabled_features {
386 assert!(v2.has_feature(feature));
387 }
388
389 assert!(v2.enabled_features.len() > v1.enabled_features.len());
391
392 assert!(v1.deprecated_features.is_empty());
394
395 assert!(!v2.deprecated_features.is_empty());
397 }
398}