1use crate::{NetworkParameters, ProtocolVersion, Result};
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
12pub struct NetworkConstants {
13 pub magic_bytes: [u8; 4],
15 pub default_port: u16,
17 pub genesis_hash: [u8; 32],
19 pub max_target: u32,
21 pub halving_interval: u64,
23 pub network_name: String,
25 pub is_testnet: bool,
27 pub dns_seeds: Vec<String>,
29 pub checkpoints: Vec<Checkpoint>,
31}
32
33#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
35pub struct Checkpoint {
36 pub height: u64,
38 pub hash: [u8; 32],
40 pub timestamp: u64,
42}
43
44impl NetworkConstants {
45 pub fn for_version(version: ProtocolVersion) -> Result<Self> {
47 match version {
48 ProtocolVersion::BitcoinV1 => Self::mainnet(),
49 ProtocolVersion::Testnet3 => Self::testnet(),
50 ProtocolVersion::Regtest => Self::regtest(),
51 ProtocolVersion::Signet => Self::signet(),
52 ProtocolVersion::Testnet4 => Self::testnet4(),
53 }
54 }
55
56 pub fn mainnet() -> Result<Self> {
58 Ok(Self {
59 magic_bytes: [0xf9, 0xbe, 0xb4, 0xd9], default_port: 8333,
61 genesis_hash: [
62 0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72, 0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63,
63 0xf7, 0x4f, 0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c, 0x68, 0xd6, 0x19, 0x00,
64 0x00, 0x00, 0x00, 0x00,
65 ],
66 max_target: 0x1d00ffff,
67 halving_interval: 210000,
68 network_name: "mainnet".to_string(),
69 is_testnet: false,
70 dns_seeds: vec![
71 "seed.bitcoin.sipa.be".to_string(),
72 "dnsseed.bluematt.me".to_string(),
73 "dnsseed.bitcoin.dashjr.org".to_string(),
74 "seed.bitcoinstats.com".to_string(),
75 "seed.bitcoin.jonasschnelli.ch".to_string(),
76 "seed.btc.petertodd.org".to_string(),
77 ],
78 checkpoints: Self::mainnet_checkpoints(),
79 })
80 }
81
82 pub fn testnet() -> Result<Self> {
84 Ok(Self {
85 magic_bytes: [0x0b, 0x11, 0x09, 0x07], default_port: 18333,
87 genesis_hash: [
88 0x43, 0x49, 0x7f, 0xd7, 0xf8, 0x26, 0x95, 0x71, 0x08, 0xf4, 0xa3, 0x0f, 0xd9, 0xce,
89 0xc3, 0xae, 0xba, 0x79, 0x97, 0x20, 0x84, 0xe9, 0x0e, 0xad, 0x01, 0xea, 0x33, 0x09,
90 0x00, 0x00, 0x00, 0x00,
91 ],
92 max_target: 0x1d00ffff,
93 halving_interval: 210000,
94 network_name: "testnet".to_string(),
95 is_testnet: true,
96 dns_seeds: vec![
97 "testnet-seed.bitcoin.jonasschnelli.ch".to_string(),
98 "seed.tbtc.petertodd.org".to_string(),
99 "seed.testnet.bitcoin.sprovoost.nl".to_string(),
100 "testnet-seed.bluematt.me".to_string(),
101 ],
102 checkpoints: Self::testnet_checkpoints(),
103 })
104 }
105
106 pub fn regtest() -> Result<Self> {
108 Ok(Self {
109 magic_bytes: [0xfa, 0xbf, 0xb5, 0xda], default_port: 18444,
111 genesis_hash: [
112 0x06, 0x22, 0x6e, 0x46, 0x11, 0x1a, 0x0b, 0x59, 0xca, 0xaf, 0x12, 0x60, 0x43, 0xeb,
113 0x5b, 0xbf, 0x28, 0xc3, 0x4f, 0x3a, 0x5e, 0x33, 0x2a, 0x1f, 0xc7, 0xb2, 0xb7, 0x3c,
114 0xf1, 0x88, 0x91, 0x0f,
115 ],
116 max_target: 0x207fffff, halving_interval: 150, network_name: "regtest".to_string(),
119 is_testnet: true,
120 dns_seeds: vec![], checkpoints: vec![], })
123 }
124
125 pub fn signet() -> Result<Self> {
127 Ok(Self {
128 magic_bytes: [0x0f, 0x1b, 0xf2, 0xe1],
129 default_port: 38333,
130 genesis_hash: [
131 0xf6, 0x1e, 0xee, 0x3b, 0x63, 0xa3, 0x80, 0xa4, 0x77, 0xa0, 0x63, 0xaf, 0x32, 0xb2,
132 0xbb, 0xc9, 0x7c, 0x9f, 0xf9, 0xf0, 0x1f, 0x2c, 0x42, 0x25, 0xe9, 0x73, 0x98, 0x81,
133 0x08, 0x00, 0x00, 0x00,
134 ],
135 max_target: 0x1e0377ae,
136 halving_interval: 210_000,
137 network_name: "signet".to_string(),
138 is_testnet: true,
139 dns_seeds: vec![
140 "seed.signet.bitcoin.sprovoost.nl".to_string(),
141 "seed.signet.achownodes.xyz".to_string(),
142 ],
143 checkpoints: vec![],
144 })
145 }
146
147 pub fn testnet4() -> Result<Self> {
149 let genesis = crate::genesis::testnet4_genesis();
150 Ok(Self {
151 magic_bytes: [0x1c, 0x16, 0x3f, 0x28],
152 default_port: 48333,
153 genesis_hash: blvm_consensus::block::block_header_hash(&genesis.header),
154 max_target: 0x1d00ffff,
155 halving_interval: 210_000,
156 network_name: "testnet4".to_string(),
157 is_testnet: true,
158 dns_seeds: vec![
159 "seed.testnet4.bitcoin.sprovoost.nl".to_string(),
160 "seed.testnet4.wiz.biz".to_string(),
161 ],
162 checkpoints: vec![],
163 })
164 }
165
166 fn mainnet_checkpoints() -> Vec<Checkpoint> {
168 vec![
169 Checkpoint {
170 height: 11111,
171 hash: [
172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175 ],
176 timestamp: 1231006505,
177 },
178 ]
180 }
181
182 fn testnet_checkpoints() -> Vec<Checkpoint> {
184 vec![
185 Checkpoint {
186 height: 11111,
187 hash: [
188 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191 ],
192 timestamp: 1296688602,
193 },
194 ]
196 }
197}
198
199impl NetworkParameters {
200 pub fn from_constants(constants: &NetworkConstants) -> Result<Self> {
202 let genesis_block = match constants.network_name.as_str() {
203 "testnet" => crate::genesis::testnet_genesis(),
204 "regtest" => crate::genesis::regtest_genesis(),
205 "signet" => crate::genesis::signet_genesis(),
206 _ => crate::genesis::mainnet_genesis(),
207 };
208 Ok(NetworkParameters {
209 magic_bytes: constants.magic_bytes,
210 default_port: constants.default_port,
211 genesis_block,
212 max_target: constants.max_target,
213 halving_interval: constants.halving_interval,
214 network_name: constants.network_name.clone(),
215 is_testnet: constants.is_testnet,
216 signet_challenge: None,
217 })
218 }
219}
220
221#[cfg(test)]
222mod tests {
223 use super::*;
224
225 #[test]
226 fn test_network_constants() {
227 let mainnet = NetworkConstants::mainnet().unwrap();
228 assert_eq!(mainnet.magic_bytes, [0xf9, 0xbe, 0xb4, 0xd9]);
229 assert_eq!(mainnet.default_port, 8333);
230 assert!(!mainnet.is_testnet);
231 assert!(!mainnet.dns_seeds.is_empty());
232
233 let testnet = NetworkConstants::testnet().unwrap();
234 assert_eq!(testnet.magic_bytes, [0x0b, 0x11, 0x09, 0x07]);
235 assert_eq!(testnet.default_port, 18333);
236 assert!(testnet.is_testnet);
237
238 let regtest = NetworkConstants::regtest().unwrap();
239 assert_eq!(regtest.magic_bytes, [0xfa, 0xbf, 0xb5, 0xda]);
240 assert_eq!(regtest.default_port, 18444);
241 assert!(regtest.is_testnet);
242 assert!(regtest.dns_seeds.is_empty());
243
244 let signet = NetworkConstants::signet().unwrap();
245 assert_eq!(signet.magic_bytes, [0x0f, 0x1b, 0xf2, 0xe1]);
246 assert_eq!(signet.default_port, 38333);
247 assert!(signet.is_testnet);
248 assert!(!signet.dns_seeds.is_empty());
249 }
250
251 #[test]
252 fn test_network_parameters_from_constants() {
253 let constants = NetworkConstants::mainnet().unwrap();
254 let params = NetworkParameters::from_constants(&constants).unwrap();
255
256 assert_eq!(params.magic_bytes, constants.magic_bytes);
257 assert_eq!(params.default_port, constants.default_port);
258 assert_eq!(params.network_name, constants.network_name);
259 assert_eq!(params.is_testnet, constants.is_testnet);
260 }
261
262 #[test]
263 fn test_network_constants_for_version() {
264 let mainnet = NetworkConstants::for_version(ProtocolVersion::BitcoinV1).unwrap();
265 assert_eq!(mainnet.network_name, "mainnet");
266 assert!(!mainnet.is_testnet);
267
268 let testnet = NetworkConstants::for_version(ProtocolVersion::Testnet3).unwrap();
269 assert_eq!(testnet.network_name, "testnet");
270 assert!(testnet.is_testnet);
271
272 let regtest = NetworkConstants::for_version(ProtocolVersion::Regtest).unwrap();
273 assert_eq!(regtest.network_name, "regtest");
274 assert!(regtest.is_testnet);
275
276 let signet = NetworkConstants::for_version(ProtocolVersion::Signet).unwrap();
277 assert_eq!(signet.network_name, "signet");
278 assert!(signet.is_testnet);
279 }
280
281 #[test]
282 fn test_genesis_hashes() {
283 let mainnet = NetworkConstants::mainnet().unwrap();
284 let testnet = NetworkConstants::testnet().unwrap();
285 let regtest = NetworkConstants::regtest().unwrap();
286
287 assert_ne!(mainnet.genesis_hash, testnet.genesis_hash);
289 assert_ne!(testnet.genesis_hash, regtest.genesis_hash);
290 assert_ne!(mainnet.genesis_hash, regtest.genesis_hash);
291
292 let signet = NetworkConstants::signet().unwrap();
293 assert_ne!(signet.genesis_hash, mainnet.genesis_hash);
294 assert_ne!(signet.genesis_hash, testnet.genesis_hash);
295 assert_ne!(signet.genesis_hash, regtest.genesis_hash);
296
297 assert_ne!(mainnet.genesis_hash, [0u8; 32]);
299 assert_ne!(testnet.genesis_hash, [0u8; 32]);
300 assert_ne!(regtest.genesis_hash, [0u8; 32]);
301 }
302
303 #[test]
304 fn test_dns_seeds() {
305 let mainnet = NetworkConstants::mainnet().unwrap();
306 let testnet = NetworkConstants::testnet().unwrap();
307 let regtest = NetworkConstants::regtest().unwrap();
308
309 assert!(!mainnet.dns_seeds.is_empty());
311 assert!(
312 mainnet
313 .dns_seeds
314 .iter()
315 .any(|seed| seed.contains("bitcoin"))
316 );
317
318 assert!(!testnet.dns_seeds.is_empty());
320 assert!(
321 testnet
322 .dns_seeds
323 .iter()
324 .any(|seed| seed.contains("testnet"))
325 );
326
327 assert!(regtest.dns_seeds.is_empty());
329 }
330
331 #[test]
332 fn test_checkpoints() {
333 let mainnet = NetworkConstants::mainnet().unwrap();
334 let testnet = NetworkConstants::testnet().unwrap();
335 let regtest = NetworkConstants::regtest().unwrap();
336
337 assert!(!mainnet.checkpoints.is_empty());
339
340 assert!(!testnet.checkpoints.is_empty());
342
343 assert!(regtest.checkpoints.is_empty());
345
346 for checkpoints in [&mainnet.checkpoints, &testnet.checkpoints] {
348 for i in 1..checkpoints.len() {
349 assert!(checkpoints[i].height > checkpoints[i - 1].height);
350 }
351 }
352 }
353
354 #[test]
355 fn test_max_targets() {
356 let mainnet = NetworkConstants::mainnet().unwrap();
357 let testnet = NetworkConstants::testnet().unwrap();
358 let regtest = NetworkConstants::regtest().unwrap();
359
360 assert_eq!(mainnet.max_target, 0x1d00ffff);
362 assert_eq!(testnet.max_target, 0x1d00ffff);
363
364 assert_eq!(regtest.max_target, 0x207fffff);
366 assert!(regtest.max_target > mainnet.max_target);
367 }
368
369 #[test]
370 fn test_halving_intervals() {
371 let mainnet = NetworkConstants::mainnet().unwrap();
372 let testnet = NetworkConstants::testnet().unwrap();
373 let regtest = NetworkConstants::regtest().unwrap();
374
375 assert_eq!(mainnet.halving_interval, 210000);
377 assert_eq!(testnet.halving_interval, 210000);
378
379 assert_eq!(regtest.halving_interval, 150);
381 assert!(regtest.halving_interval < mainnet.halving_interval);
382 }
383
384 #[test]
385 fn test_network_constants_serialization() {
386 let mainnet = NetworkConstants::mainnet().unwrap();
387 let testnet = NetworkConstants::testnet().unwrap();
388 let regtest = NetworkConstants::regtest().unwrap();
389
390 for constants in [mainnet, testnet, regtest] {
392 let json = serde_json::to_string(&constants).unwrap();
393 let deserialized: NetworkConstants = serde_json::from_str(&json).unwrap();
394
395 assert_eq!(constants.magic_bytes, deserialized.magic_bytes);
396 assert_eq!(constants.default_port, deserialized.default_port);
397 assert_eq!(constants.genesis_hash, deserialized.genesis_hash);
398 assert_eq!(constants.max_target, deserialized.max_target);
399 assert_eq!(constants.halving_interval, deserialized.halving_interval);
400 assert_eq!(constants.network_name, deserialized.network_name);
401 assert_eq!(constants.is_testnet, deserialized.is_testnet);
402 assert_eq!(constants.dns_seeds, deserialized.dns_seeds);
403 assert_eq!(constants.checkpoints, deserialized.checkpoints);
404 }
405 }
406
407 #[test]
408 fn test_checkpoint_serialization() {
409 let checkpoint = Checkpoint {
410 height: 1000,
411 hash: [
412 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02,
413 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04,
414 0x01, 0x02, 0x03, 0x04,
415 ],
416 timestamp: 1234567890,
417 };
418
419 let json = serde_json::to_string(&checkpoint).unwrap();
420 let deserialized: Checkpoint = serde_json::from_str(&json).unwrap();
421
422 assert_eq!(checkpoint.height, deserialized.height);
423 assert_eq!(checkpoint.hash, deserialized.hash);
424 assert_eq!(checkpoint.timestamp, deserialized.timestamp);
425 }
426
427 #[test]
428 fn test_network_constants_equality() {
429 let mainnet1 = NetworkConstants::mainnet().unwrap();
430 let mainnet2 = NetworkConstants::mainnet().unwrap();
431 let testnet = NetworkConstants::testnet().unwrap();
432
433 assert_eq!(mainnet1, mainnet2);
434 assert_ne!(mainnet1, testnet);
435 }
436
437 #[test]
438 fn test_checkpoint_equality() {
439 let checkpoint1 = Checkpoint {
440 height: 1000,
441 hash: [0x01; 32],
442 timestamp: 1234567890,
443 };
444
445 let checkpoint2 = Checkpoint {
446 height: 1000,
447 hash: [0x01; 32],
448 timestamp: 1234567890,
449 };
450
451 let checkpoint3 = Checkpoint {
452 height: 1001,
453 hash: [0x01; 32],
454 timestamp: 1234567890,
455 };
456
457 assert_eq!(checkpoint1, checkpoint2);
458 assert_ne!(checkpoint1, checkpoint3);
459 }
460
461 #[test]
462 fn test_network_parameters_consistency() {
463 let mainnet_constants = NetworkConstants::mainnet().unwrap();
464 let mainnet_params = NetworkParameters::from_constants(&mainnet_constants).unwrap();
465
466 assert_eq!(mainnet_params.magic_bytes, mainnet_constants.magic_bytes);
467 assert_eq!(mainnet_params.default_port, mainnet_constants.default_port);
468 assert_eq!(mainnet_params.max_target, mainnet_constants.max_target);
469 assert_eq!(
470 mainnet_params.halving_interval,
471 mainnet_constants.halving_interval
472 );
473 assert_eq!(mainnet_params.network_name, mainnet_constants.network_name);
474 assert_eq!(mainnet_params.is_testnet, mainnet_constants.is_testnet);
475 }
476
477 #[test]
478 fn test_all_networks_have_unique_magic_bytes() {
479 let mainnet = NetworkConstants::mainnet().unwrap();
480 let testnet = NetworkConstants::testnet().unwrap();
481 let regtest = NetworkConstants::regtest().unwrap();
482
483 assert_ne!(mainnet.magic_bytes, testnet.magic_bytes);
484 assert_ne!(testnet.magic_bytes, regtest.magic_bytes);
485 assert_ne!(mainnet.magic_bytes, regtest.magic_bytes);
486 }
487
488 #[test]
489 fn test_all_networks_have_unique_ports() {
490 let mainnet = NetworkConstants::mainnet().unwrap();
491 let testnet = NetworkConstants::testnet().unwrap();
492 let regtest = NetworkConstants::regtest().unwrap();
493
494 assert_ne!(mainnet.default_port, testnet.default_port);
495 assert_ne!(testnet.default_port, regtest.default_port);
496 assert_ne!(mainnet.default_port, regtest.default_port);
497 }
498
499 #[test]
500 fn test_network_names() {
501 let mainnet = NetworkConstants::mainnet().unwrap();
502 let testnet = NetworkConstants::testnet().unwrap();
503 let regtest = NetworkConstants::regtest().unwrap();
504
505 assert_eq!(mainnet.network_name, "mainnet");
506 assert_eq!(testnet.network_name, "testnet");
507 assert_eq!(regtest.network_name, "regtest");
508 }
509
510 #[test]
511 fn test_testnet_flags() {
512 let mainnet = NetworkConstants::mainnet().unwrap();
513 let testnet = NetworkConstants::testnet().unwrap();
514 let regtest = NetworkConstants::regtest().unwrap();
515
516 assert!(!mainnet.is_testnet);
517 assert!(testnet.is_testnet);
518 assert!(regtest.is_testnet);
519 }
520}