1pub use super::{
2 bps::{Bps, Testnet11Bps},
3 constants::consensus::*,
4 genesis::{GenesisBlock, DEVNET_GENESIS, GENESIS, SIMNET_GENESIS, TESTNET11_GENESIS, TESTNET_GENESIS},
5};
6use crate::{
7 constants::STORAGE_MASS_PARAMETER,
8 network::{NetworkId, NetworkType},
9 BlockLevel, KType,
10};
11use kaspa_addresses::Prefix;
12use kaspa_math::Uint256;
13use std::{
14 cmp::min,
15 time::{SystemTime, UNIX_EPOCH},
16};
17
18#[derive(Clone, Debug)]
22pub struct Params {
23 pub dns_seeders: &'static [&'static str],
24 pub net: NetworkId,
25 pub genesis: GenesisBlock,
26 pub ghostdag_k: KType,
27
28 pub legacy_timestamp_deviation_tolerance: u64,
30
31 pub new_timestamp_deviation_tolerance: u64,
33
34 pub past_median_time_sample_rate: u64,
36
37 pub past_median_time_sampled_window_size: u64,
39
40 pub target_time_per_block: u64,
42
43 pub sampling_activation_daa_score: u64,
45
46 pub max_difficulty_target: Uint256,
48
49 pub max_difficulty_target_f64: f64,
51
52 pub difficulty_sample_rate: u64,
54
55 pub sampled_difficulty_window_size: usize,
57
58 pub legacy_difficulty_window_size: usize,
60
61 pub min_difficulty_window_len: usize,
63
64 pub max_block_parents: u8,
65 pub mergeset_size_limit: u64,
66 pub merge_depth: u64,
67 pub finality_depth: u64,
68 pub pruning_depth: u64,
69 pub coinbase_payload_script_public_key_max_len: u8,
70 pub max_coinbase_payload_len: usize,
71 pub max_tx_inputs: usize,
72 pub max_tx_outputs: usize,
73 pub max_signature_script_len: usize,
74 pub max_script_public_key_len: usize,
75 pub mass_per_tx_byte: u64,
76 pub mass_per_script_pub_key_byte: u64,
77 pub mass_per_sig_op: u64,
78 pub max_block_mass: u64,
79
80 pub storage_mass_parameter: u64,
82
83 pub storage_mass_activation_daa_score: u64,
85
86 pub deflationary_phase_daa_score: u64,
88
89 pub pre_deflationary_phase_base_subsidy: u64,
90 pub coinbase_maturity: u64,
91 pub skip_proof_of_work: bool,
92 pub max_block_level: BlockLevel,
93 pub pruning_proof_m: u64,
94}
95
96fn unix_now() -> u64 {
97 SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis() as u64
98}
99
100impl Params {
101 #[inline]
103 #[must_use]
104 pub fn legacy_past_median_time_window_size(&self) -> usize {
105 (2 * self.legacy_timestamp_deviation_tolerance - 1) as usize
106 }
107
108 #[inline]
110 #[must_use]
111 pub fn sampled_past_median_time_window_size(&self) -> usize {
112 self.past_median_time_sampled_window_size as usize
113 }
114
115 #[inline]
118 #[must_use]
119 pub fn past_median_time_window_size(&self, selected_parent_daa_score: u64) -> usize {
120 if selected_parent_daa_score < self.sampling_activation_daa_score {
121 self.legacy_past_median_time_window_size()
122 } else {
123 self.sampled_past_median_time_window_size()
124 }
125 }
126
127 #[inline]
130 #[must_use]
131 pub fn timestamp_deviation_tolerance(&self, selected_parent_daa_score: u64) -> u64 {
132 if selected_parent_daa_score < self.sampling_activation_daa_score {
133 self.legacy_timestamp_deviation_tolerance
134 } else {
135 self.new_timestamp_deviation_tolerance
136 }
137 }
138
139 #[inline]
142 #[must_use]
143 pub fn past_median_time_sample_rate(&self, selected_parent_daa_score: u64) -> u64 {
144 if selected_parent_daa_score < self.sampling_activation_daa_score {
145 1
146 } else {
147 self.past_median_time_sample_rate
148 }
149 }
150
151 #[inline]
154 #[must_use]
155 pub fn difficulty_window_size(&self, selected_parent_daa_score: u64) -> usize {
156 if selected_parent_daa_score < self.sampling_activation_daa_score {
157 self.legacy_difficulty_window_size
158 } else {
159 self.sampled_difficulty_window_size
160 }
161 }
162
163 #[inline]
166 #[must_use]
167 pub fn difficulty_sample_rate(&self, selected_parent_daa_score: u64) -> u64 {
168 if selected_parent_daa_score < self.sampling_activation_daa_score {
169 1
170 } else {
171 self.difficulty_sample_rate
172 }
173 }
174
175 #[inline]
178 #[must_use]
179 pub fn target_time_per_block(&self, _selected_parent_daa_score: u64) -> u64 {
180 self.target_time_per_block
181 }
182
183 #[inline]
185 #[must_use]
186 pub fn bps(&self) -> u64 {
187 1000 / self.target_time_per_block
188 }
189
190 pub fn daa_window_duration_in_blocks(&self, selected_parent_daa_score: u64) -> u64 {
191 if selected_parent_daa_score < self.sampling_activation_daa_score {
192 self.legacy_difficulty_window_size as u64
193 } else {
194 self.difficulty_sample_rate * self.sampled_difficulty_window_size as u64
195 }
196 }
197
198 fn expected_daa_window_duration_in_milliseconds(&self, selected_parent_daa_score: u64) -> u64 {
199 if selected_parent_daa_score < self.sampling_activation_daa_score {
200 self.target_time_per_block * self.legacy_difficulty_window_size as u64
201 } else {
202 self.target_time_per_block * self.difficulty_sample_rate * self.sampled_difficulty_window_size as u64
203 }
204 }
205
206 pub fn anticone_finalization_depth(&self) -> u64 {
210 let anticone_finalization_depth = self.finality_depth
211 + self.merge_depth
212 + 4 * self.mergeset_size_limit * self.ghostdag_k as u64
213 + 2 * self.ghostdag_k as u64
214 + 2;
215
216 min(self.pruning_depth, anticone_finalization_depth)
222 }
223
224 pub fn is_nearly_synced(&self, sink_timestamp: u64, sink_daa_score: u64) -> bool {
226 if self.net.is_mainnet() {
227 unix_now() < sink_timestamp + self.expected_daa_window_duration_in_milliseconds(sink_daa_score)
231 } else {
232 let max_expected_duration_without_blocks_in_milliseconds = self.target_time_per_block * NEW_DIFFICULTY_WINDOW_DURATION / 3; unix_now() < sink_timestamp + max_expected_duration_without_blocks_in_milliseconds
241 }
242 }
243
244 pub fn network_name(&self) -> String {
245 self.net.to_prefixed()
246 }
247
248 pub fn prefix(&self) -> Prefix {
249 self.net.into()
250 }
251
252 pub fn default_p2p_port(&self) -> u16 {
253 self.net.default_p2p_port()
254 }
255
256 pub fn default_rpc_port(&self) -> u16 {
257 self.net.default_rpc_port()
258 }
259
260 pub fn finality_duration(&self) -> u64 {
261 self.target_time_per_block * self.finality_depth
262 }
263}
264
265impl From<NetworkType> for Params {
266 fn from(value: NetworkType) -> Self {
267 match value {
268 NetworkType::Mainnet => MAINNET_PARAMS,
269 NetworkType::Testnet => TESTNET_PARAMS,
270 NetworkType::Devnet => DEVNET_PARAMS,
271 NetworkType::Simnet => SIMNET_PARAMS,
272 }
273 }
274}
275
276impl From<NetworkId> for Params {
277 fn from(value: NetworkId) -> Self {
278 match value.network_type {
279 NetworkType::Mainnet => MAINNET_PARAMS,
280 NetworkType::Testnet => match value.suffix {
281 Some(10) => TESTNET_PARAMS,
282 Some(11) => TESTNET11_PARAMS,
283 Some(x) => panic!("Testnet suffix {} is not supported", x),
284 None => panic!("Testnet suffix not provided"),
285 },
286 NetworkType::Devnet => DEVNET_PARAMS,
287 NetworkType::Simnet => SIMNET_PARAMS,
288 }
289 }
290}
291
292pub const MAINNET_PARAMS: Params = Params {
293 dns_seeders: &[
294 "mainnet-dnsseed-1.kaspanet.org",
296 "mainnet-dnsseed-2.kaspanet.org",
298 "dnsseed.cbytensky.org",
300 "seeder1.kaspad.net",
302 "seeder2.kaspad.net",
304 "seeder3.kaspad.net",
306 "seeder4.kaspad.net",
308 "kaspadns.kaspacalc.net",
310 "n-mainnet.kaspa.ws",
312 "dnsseeder-kaspa-mainnet.x-con.at",
314 "ns-mainnet.kaspa-dnsseeder.net",
316 ],
317 net: NetworkId::new(NetworkType::Mainnet),
318 genesis: GENESIS,
319 ghostdag_k: LEGACY_DEFAULT_GHOSTDAG_K,
320 legacy_timestamp_deviation_tolerance: LEGACY_TIMESTAMP_DEVIATION_TOLERANCE,
321 new_timestamp_deviation_tolerance: NEW_TIMESTAMP_DEVIATION_TOLERANCE,
322 past_median_time_sample_rate: Bps::<1>::past_median_time_sample_rate(),
323 past_median_time_sampled_window_size: MEDIAN_TIME_SAMPLED_WINDOW_SIZE,
324 target_time_per_block: 1000,
325 sampling_activation_daa_score: u64::MAX,
326 max_difficulty_target: MAX_DIFFICULTY_TARGET,
327 max_difficulty_target_f64: MAX_DIFFICULTY_TARGET_AS_F64,
328 difficulty_sample_rate: Bps::<1>::difficulty_adjustment_sample_rate(),
329 sampled_difficulty_window_size: DIFFICULTY_SAMPLED_WINDOW_SIZE as usize,
330 legacy_difficulty_window_size: LEGACY_DIFFICULTY_WINDOW_SIZE,
331 min_difficulty_window_len: MIN_DIFFICULTY_WINDOW_LEN,
332 max_block_parents: 10,
333 mergeset_size_limit: (LEGACY_DEFAULT_GHOSTDAG_K as u64) * 10,
334 merge_depth: 3600,
335 finality_depth: 86400,
336 pruning_depth: 185798,
337 coinbase_payload_script_public_key_max_len: 150,
338 max_coinbase_payload_len: 204,
339
340 max_tx_inputs: 1_000_000_000,
345 max_tx_outputs: 1_000_000_000,
346 max_signature_script_len: 1_000_000_000,
347 max_script_public_key_len: 1_000_000_000,
348
349 mass_per_tx_byte: 1,
350 mass_per_script_pub_key_byte: 10,
351 mass_per_sig_op: 1000,
352 max_block_mass: 500_000,
353
354 storage_mass_parameter: STORAGE_MASS_PARAMETER,
355 storage_mass_activation_daa_score: u64::MAX,
356
357 deflationary_phase_daa_score: 15778800 - 259200,
364 pre_deflationary_phase_base_subsidy: 50000000000,
365 coinbase_maturity: 100,
366 skip_proof_of_work: false,
367 max_block_level: 225,
368 pruning_proof_m: 1000,
369};
370
371pub const TESTNET_PARAMS: Params = Params {
372 dns_seeders: &[
373 "seeder1-testnet.kaspad.net",
375 "dnsseeder-kaspa-testnet.x-con.at",
377 "ns-testnet10.kaspa-dnsseeder.net",
379 ],
380 net: NetworkId::with_suffix(NetworkType::Testnet, 10),
381 genesis: TESTNET_GENESIS,
382 ghostdag_k: LEGACY_DEFAULT_GHOSTDAG_K,
383 legacy_timestamp_deviation_tolerance: LEGACY_TIMESTAMP_DEVIATION_TOLERANCE,
384 new_timestamp_deviation_tolerance: NEW_TIMESTAMP_DEVIATION_TOLERANCE,
385 past_median_time_sample_rate: Bps::<1>::past_median_time_sample_rate(),
386 past_median_time_sampled_window_size: MEDIAN_TIME_SAMPLED_WINDOW_SIZE,
387 target_time_per_block: 1000,
388 sampling_activation_daa_score: u64::MAX,
389 max_difficulty_target: MAX_DIFFICULTY_TARGET,
390 max_difficulty_target_f64: MAX_DIFFICULTY_TARGET_AS_F64,
391 difficulty_sample_rate: Bps::<1>::difficulty_adjustment_sample_rate(),
392 sampled_difficulty_window_size: DIFFICULTY_SAMPLED_WINDOW_SIZE as usize,
393 legacy_difficulty_window_size: LEGACY_DIFFICULTY_WINDOW_SIZE,
394 min_difficulty_window_len: MIN_DIFFICULTY_WINDOW_LEN,
395 max_block_parents: 10,
396 mergeset_size_limit: (LEGACY_DEFAULT_GHOSTDAG_K as u64) * 10,
397 merge_depth: 3600,
398 finality_depth: 86400,
399 pruning_depth: 185798,
400 coinbase_payload_script_public_key_max_len: 150,
401 max_coinbase_payload_len: 204,
402
403 max_tx_inputs: 1_000_000_000,
408 max_tx_outputs: 1_000_000_000,
409 max_signature_script_len: 1_000_000_000,
410 max_script_public_key_len: 1_000_000_000,
411
412 mass_per_tx_byte: 1,
413 mass_per_script_pub_key_byte: 10,
414 mass_per_sig_op: 1000,
415 max_block_mass: 500_000,
416
417 storage_mass_parameter: STORAGE_MASS_PARAMETER,
418 storage_mass_activation_daa_score: u64::MAX,
419
420 deflationary_phase_daa_score: 15778800 - 259200,
427 pre_deflationary_phase_base_subsidy: 50000000000,
428 coinbase_maturity: 100,
429 skip_proof_of_work: false,
430 max_block_level: 250,
431 pruning_proof_m: 1000,
432};
433
434pub const TESTNET11_PARAMS: Params = Params {
435 dns_seeders: &[
436 "seeder1-testnet-11.kaspad.net",
438 "n-testnet-11.kaspa.ws",
440 "dnsseeder-kaspa-testnet11.x-con.at",
442 "ns-testnet11.kaspa-dnsseeder.net",
444 ],
445 net: NetworkId::with_suffix(NetworkType::Testnet, 11),
446 genesis: TESTNET11_GENESIS,
447 legacy_timestamp_deviation_tolerance: LEGACY_TIMESTAMP_DEVIATION_TOLERANCE,
448 new_timestamp_deviation_tolerance: NEW_TIMESTAMP_DEVIATION_TOLERANCE,
449 past_median_time_sampled_window_size: MEDIAN_TIME_SAMPLED_WINDOW_SIZE,
450 sampling_activation_daa_score: 0, max_difficulty_target: MAX_DIFFICULTY_TARGET,
452 max_difficulty_target_f64: MAX_DIFFICULTY_TARGET_AS_F64,
453 sampled_difficulty_window_size: DIFFICULTY_SAMPLED_WINDOW_SIZE as usize,
454 legacy_difficulty_window_size: LEGACY_DIFFICULTY_WINDOW_SIZE,
455 min_difficulty_window_len: MIN_DIFFICULTY_WINDOW_LEN,
456
457 ghostdag_k: Testnet11Bps::ghostdag_k(),
461 target_time_per_block: Testnet11Bps::target_time_per_block(),
462 past_median_time_sample_rate: Testnet11Bps::past_median_time_sample_rate(),
463 difficulty_sample_rate: Testnet11Bps::difficulty_adjustment_sample_rate(),
464 max_block_parents: Testnet11Bps::max_block_parents(),
465 mergeset_size_limit: Testnet11Bps::mergeset_size_limit(),
466 merge_depth: Testnet11Bps::merge_depth_bound(),
467 finality_depth: Testnet11Bps::finality_depth(),
468 pruning_depth: Testnet11Bps::pruning_depth(),
469 pruning_proof_m: Testnet11Bps::pruning_proof_m(),
470 deflationary_phase_daa_score: Testnet11Bps::deflationary_phase_daa_score(),
471 pre_deflationary_phase_base_subsidy: Testnet11Bps::pre_deflationary_phase_base_subsidy(),
472 coinbase_maturity: Testnet11Bps::coinbase_maturity(),
473
474 coinbase_payload_script_public_key_max_len: 150,
475 max_coinbase_payload_len: 204,
476
477 max_tx_inputs: 10_000,
478 max_tx_outputs: 10_000,
479 max_signature_script_len: 1_000_000,
480 max_script_public_key_len: 1_000_000,
481
482 mass_per_tx_byte: 1,
483 mass_per_script_pub_key_byte: 10,
484 mass_per_sig_op: 1000,
485 max_block_mass: 500_000,
486
487 storage_mass_parameter: STORAGE_MASS_PARAMETER,
488 storage_mass_activation_daa_score: 0,
489
490 skip_proof_of_work: false,
491 max_block_level: 250,
492};
493
494pub const SIMNET_PARAMS: Params = Params {
495 dns_seeders: &[],
496 net: NetworkId::new(NetworkType::Simnet),
497 genesis: SIMNET_GENESIS,
498 legacy_timestamp_deviation_tolerance: LEGACY_TIMESTAMP_DEVIATION_TOLERANCE,
499 new_timestamp_deviation_tolerance: NEW_TIMESTAMP_DEVIATION_TOLERANCE,
500 past_median_time_sampled_window_size: MEDIAN_TIME_SAMPLED_WINDOW_SIZE,
501 sampling_activation_daa_score: 0, max_difficulty_target: MAX_DIFFICULTY_TARGET,
503 max_difficulty_target_f64: MAX_DIFFICULTY_TARGET_AS_F64,
504 sampled_difficulty_window_size: DIFFICULTY_SAMPLED_WINDOW_SIZE as usize,
505 legacy_difficulty_window_size: LEGACY_DIFFICULTY_WINDOW_SIZE,
506 min_difficulty_window_len: MIN_DIFFICULTY_WINDOW_LEN,
507
508 ghostdag_k: Testnet11Bps::ghostdag_k(),
513 target_time_per_block: Testnet11Bps::target_time_per_block(),
514 past_median_time_sample_rate: Testnet11Bps::past_median_time_sample_rate(),
515 difficulty_sample_rate: Testnet11Bps::difficulty_adjustment_sample_rate(),
516 max_block_parents: if Testnet11Bps::max_block_parents() > 64 { Testnet11Bps::max_block_parents() } else { 64 },
518 mergeset_size_limit: Testnet11Bps::mergeset_size_limit(),
519 merge_depth: Testnet11Bps::merge_depth_bound(),
520 finality_depth: Testnet11Bps::finality_depth(),
521 pruning_depth: Testnet11Bps::pruning_depth(),
522 pruning_proof_m: Testnet11Bps::pruning_proof_m(),
523 deflationary_phase_daa_score: Testnet11Bps::deflationary_phase_daa_score(),
524 pre_deflationary_phase_base_subsidy: Testnet11Bps::pre_deflationary_phase_base_subsidy(),
525 coinbase_maturity: Testnet11Bps::coinbase_maturity(),
526
527 coinbase_payload_script_public_key_max_len: 150,
528 max_coinbase_payload_len: 204,
529
530 max_tx_inputs: 10_000,
531 max_tx_outputs: 10_000,
532 max_signature_script_len: 1_000_000,
533 max_script_public_key_len: 1_000_000,
534
535 mass_per_tx_byte: 1,
536 mass_per_script_pub_key_byte: 10,
537 mass_per_sig_op: 1000,
538 max_block_mass: 500_000,
539
540 storage_mass_parameter: STORAGE_MASS_PARAMETER,
541 storage_mass_activation_daa_score: 0,
542
543 skip_proof_of_work: true, max_block_level: 250,
545};
546
547pub const DEVNET_PARAMS: Params = Params {
548 dns_seeders: &[],
549 net: NetworkId::new(NetworkType::Devnet),
550 genesis: DEVNET_GENESIS,
551 ghostdag_k: LEGACY_DEFAULT_GHOSTDAG_K,
552 legacy_timestamp_deviation_tolerance: LEGACY_TIMESTAMP_DEVIATION_TOLERANCE,
553 new_timestamp_deviation_tolerance: NEW_TIMESTAMP_DEVIATION_TOLERANCE,
554 past_median_time_sample_rate: Bps::<1>::past_median_time_sample_rate(),
555 past_median_time_sampled_window_size: MEDIAN_TIME_SAMPLED_WINDOW_SIZE,
556 target_time_per_block: 1000,
557 sampling_activation_daa_score: u64::MAX,
558 max_difficulty_target: MAX_DIFFICULTY_TARGET,
559 max_difficulty_target_f64: MAX_DIFFICULTY_TARGET_AS_F64,
560 difficulty_sample_rate: Bps::<1>::difficulty_adjustment_sample_rate(),
561 sampled_difficulty_window_size: DIFFICULTY_SAMPLED_WINDOW_SIZE as usize,
562 legacy_difficulty_window_size: LEGACY_DIFFICULTY_WINDOW_SIZE,
563 min_difficulty_window_len: MIN_DIFFICULTY_WINDOW_LEN,
564 max_block_parents: 10,
565 mergeset_size_limit: (LEGACY_DEFAULT_GHOSTDAG_K as u64) * 10,
566 merge_depth: 3600,
567 finality_depth: 86400,
568 pruning_depth: 185798,
569 coinbase_payload_script_public_key_max_len: 150,
570 max_coinbase_payload_len: 204,
571
572 max_tx_inputs: 1_000_000_000,
577 max_tx_outputs: 1_000_000_000,
578 max_signature_script_len: 1_000_000_000,
579 max_script_public_key_len: 1_000_000_000,
580
581 mass_per_tx_byte: 1,
582 mass_per_script_pub_key_byte: 10,
583 mass_per_sig_op: 1000,
584 max_block_mass: 500_000,
585
586 storage_mass_parameter: STORAGE_MASS_PARAMETER,
587 storage_mass_activation_daa_score: u64::MAX,
588
589 deflationary_phase_daa_score: 15778800 - 259200,
596 pre_deflationary_phase_base_subsidy: 50000000000,
597 coinbase_maturity: 100,
598 skip_proof_of_work: false,
599 max_block_level: 250,
600 pruning_proof_m: 1000,
601};