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