1use crate::{FromBytes, ToBytes, io_error};
17
18use enum_iterator::{Sequence, last};
19use snarkvm_algorithms::snark::varuna::VarunaVersion;
20use std::io;
21
22#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Sequence)]
25#[repr(u16)]
26pub enum ConsensusVersion {
27 V1 = 1,
29 V2 = 2,
31 V3 = 3,
33 V4 = 4,
35 V5 = 5,
37 V6 = 6,
39 V7 = 7,
41 V8 = 8,
43 V9 = 9,
45 V10 = 10,
47 V11 = 11,
49 V12 = 12,
51 V13 = 13,
53 V14 = 14,
58 V15 = 15,
61 V16 = 16,
66 V17 = 17,
69 V18 = 18,
72 V19 = 19,
76}
77
78impl ToBytes for ConsensusVersion {
79 fn write_le<W: io::Write>(&self, writer: W) -> io::Result<()> {
80 (*self as u16).write_le(writer)
81 }
82}
83
84impl FromBytes for ConsensusVersion {
85 fn read_le<R: io::Read>(reader: R) -> io::Result<Self> {
86 match u16::read_le(reader)? {
87 0 => Err(io_error("Zero is not a valid consensus version")),
88 1 => Ok(Self::V1),
89 2 => Ok(Self::V2),
90 3 => Ok(Self::V3),
91 4 => Ok(Self::V4),
92 5 => Ok(Self::V5),
93 6 => Ok(Self::V6),
94 7 => Ok(Self::V7),
95 8 => Ok(Self::V8),
96 9 => Ok(Self::V9),
97 10 => Ok(Self::V10),
98 11 => Ok(Self::V11),
99 12 => Ok(Self::V12),
100 13 => Ok(Self::V13),
101 14 => Ok(Self::V14),
102 15 => Ok(Self::V15),
103 16 => Ok(Self::V16),
104 17 => Ok(Self::V17),
105 18 => Ok(Self::V18),
106 19 => Ok(Self::V19),
107 _ => Err(io_error("Invalid consensus version")),
108 }
109 }
110}
111
112impl ConsensusVersion {
113 pub fn latest() -> Self {
114 last::<ConsensusVersion>().expect("At least one ConsensusVersion should be defined.")
115 }
116}
117
118impl std::fmt::Display for ConsensusVersion {
119 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120 write!(f, "{self:?}")
122 }
123}
124
125pub(crate) const NUM_CONSENSUS_VERSIONS: usize = enum_iterator::cardinality::<ConsensusVersion>();
127
128pub const CANARY_V0_CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); NUM_CONSENSUS_VERSIONS] = [
130 (ConsensusVersion::V1, 0),
131 (ConsensusVersion::V2, 2_900_000),
132 (ConsensusVersion::V3, 4_560_000),
133 (ConsensusVersion::V4, 5_730_000),
134 (ConsensusVersion::V5, 5_780_000),
135 (ConsensusVersion::V6, 6_240_000),
136 (ConsensusVersion::V7, 6_880_000),
137 (ConsensusVersion::V8, 7_565_000),
138 (ConsensusVersion::V9, 8_028_000),
139 (ConsensusVersion::V10, 8_600_000),
140 (ConsensusVersion::V11, 9_510_000),
141 (ConsensusVersion::V12, 10_030_000),
142 (ConsensusVersion::V13, 10_881_000),
143 (ConsensusVersion::V14, 11_960_000),
144 (ConsensusVersion::V15, u32::MAX),
145 (ConsensusVersion::V16, u32::MAX),
146 (ConsensusVersion::V17, u32::MAX),
147 (ConsensusVersion::V18, u32::MAX),
148 (ConsensusVersion::V19, u32::MAX),
149];
150
151pub const MAINNET_V0_CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); NUM_CONSENSUS_VERSIONS] = [
153 (ConsensusVersion::V1, 0),
154 (ConsensusVersion::V2, 2_800_000),
155 (ConsensusVersion::V3, 4_900_000),
156 (ConsensusVersion::V4, 6_135_000),
157 (ConsensusVersion::V5, 7_060_000),
158 (ConsensusVersion::V6, 7_560_000),
159 (ConsensusVersion::V7, 7_570_000),
160 (ConsensusVersion::V8, 9_430_000),
161 (ConsensusVersion::V9, 10_272_000),
162 (ConsensusVersion::V10, 11_205_000),
163 (ConsensusVersion::V11, 12_870_000),
164 (ConsensusVersion::V12, 13_815_000),
165 (ConsensusVersion::V13, 16_850_000),
166 (ConsensusVersion::V14, 17_700_000),
167 (ConsensusVersion::V15, 19_264_000),
168 (ConsensusVersion::V16, 19_860_000),
169 (ConsensusVersion::V17, 19_860_001),
170 (ConsensusVersion::V18, 20_794_000),
171 (ConsensusVersion::V19, 21_342_000),
172];
173
174pub const TESTNET_V0_CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); NUM_CONSENSUS_VERSIONS] = [
176 (ConsensusVersion::V1, 0),
177 (ConsensusVersion::V2, 2_950_000),
178 (ConsensusVersion::V3, 4_800_000),
179 (ConsensusVersion::V4, 6_625_000),
180 (ConsensusVersion::V5, 6_765_000),
181 (ConsensusVersion::V6, 7_600_000),
182 (ConsensusVersion::V7, 8_365_000),
183 (ConsensusVersion::V8, 9_173_000),
184 (ConsensusVersion::V9, 9_800_000),
185 (ConsensusVersion::V10, 10_525_000),
186 (ConsensusVersion::V11, 11_952_000),
187 (ConsensusVersion::V12, 12_669_000),
188 (ConsensusVersion::V13, 14_906_000),
189 (ConsensusVersion::V14, 15_370_000),
190 (ConsensusVersion::V15, 16_886_000),
191 (ConsensusVersion::V16, 17_319_000),
192 (ConsensusVersion::V17, 18_295_000),
193 (ConsensusVersion::V18, 18_296_000),
194 (ConsensusVersion::V19, 18_813_000),
195];
196
197pub const TEST_CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); NUM_CONSENSUS_VERSIONS] = [
202 (ConsensusVersion::V1, 0),
203 (ConsensusVersion::V2, 5),
204 (ConsensusVersion::V3, 6),
205 (ConsensusVersion::V4, 7),
206 (ConsensusVersion::V5, 8),
207 (ConsensusVersion::V6, 9),
208 (ConsensusVersion::V7, 10),
209 (ConsensusVersion::V8, 11),
210 (ConsensusVersion::V9, 12),
211 (ConsensusVersion::V10, 13),
212 (ConsensusVersion::V11, 14),
213 (ConsensusVersion::V12, 15),
214 (ConsensusVersion::V13, 16),
215 (ConsensusVersion::V14, 17),
216 (ConsensusVersion::V15, 18),
217 (ConsensusVersion::V16, 19),
218 (ConsensusVersion::V17, 20),
219 (ConsensusVersion::V18, 21),
220 (ConsensusVersion::V19, 22),
221];
222
223#[cfg(any(test, feature = "test", feature = "test_consensus_heights"))]
224pub fn load_test_consensus_heights() -> [(ConsensusVersion, u32); NUM_CONSENSUS_VERSIONS] {
225 load_test_consensus_heights_inner(std::env::var("CONSENSUS_VERSION_HEIGHTS").ok())
227}
228
229#[cfg(any(test, feature = "test", feature = "test_consensus_heights", feature = "wasm"))]
230pub(crate) fn load_test_consensus_heights_inner(
231 consensus_version_heights: Option<String>,
232) -> [(ConsensusVersion, u32); NUM_CONSENSUS_VERSIONS] {
233 let verify_consensus_heights = |heights: &[(ConsensusVersion, u32); NUM_CONSENSUS_VERSIONS]| {
235 assert_eq!(heights[0].1, 0, "Genesis height must be 0.");
237 for window in heights.windows(2) {
239 if window[0] >= window[1] {
240 panic!("Heights must be strictly increasing, but found: {window:?}");
241 }
242 }
243 };
244
245 let mut test_consensus_heights = TEST_CONSENSUS_VERSION_HEIGHTS;
247
248 match consensus_version_heights {
250 Some(height_string) => {
251 let parsing_error = format!("Expected exactly {NUM_CONSENSUS_VERSIONS} ConsensusVersion heights.");
252 let parsed_test_consensus_heights: [u32; NUM_CONSENSUS_VERSIONS] = height_string
254 .replace(" ", "")
255 .split(",")
256 .map(|height| height.parse::<u32>().expect("Heights should be valid u32 values."))
257 .collect::<Vec<u32>>()
258 .try_into()
259 .expect(&parsing_error);
260 for (i, height) in parsed_test_consensus_heights.into_iter().enumerate() {
262 test_consensus_heights[i] = (TEST_CONSENSUS_VERSION_HEIGHTS[i].0, height);
263 }
264 verify_consensus_heights(&test_consensus_heights);
266 test_consensus_heights
267 }
268 None => {
269 verify_consensus_heights(&test_consensus_heights);
271 test_consensus_heights
272 }
273 }
274}
275
276#[macro_export]
283macro_rules! consensus_config_value {
284 ($network:ident, $constant:ident, $seek_height:expr) => {
285 $network::CONSENSUS_VERSION($seek_height).map_or(None, |seek_version| {
287 match $network::$constant.binary_search_by(|(version, _)| version.cmp(&seek_version)) {
290 Ok(index) => Some($network::$constant[index].1),
292 Err(index) => {
294 if index == 0 {
296 None
297 } else {
299 Some($network::$constant[index - 1].1)
300 }
301 }
302 }
303 })
304 };
305}
306
307#[macro_export]
314macro_rules! consensus_config_value_by_version {
315 ($network:ident, $constant:ident, $seek_version:expr) => {
316 match $network::$constant.binary_search_by(|(version, _)| version.cmp(&$seek_version)) {
318 Ok(index) => Some($network::$constant[index].1),
320 Err(index) => {
322 if index == 0 {
324 None
325 } else {
327 Some($network::$constant[index - 1].1)
328 }
329 }
330 }
331 };
332}
333
334pub fn varuna_version_from_consensus(consensus_version: ConsensusVersion) -> VarunaVersion {
336 if consensus_version >= ConsensusVersion::V4 { VarunaVersion::V2 } else { VarunaVersion::V1 }
338}
339
340#[cfg(test)]
341mod tests {
342 use super::*;
343 use crate::{CanaryV0, MainnetV0, Network, TestnetV0};
344
345 fn consensus_constants_at_genesis<N: Network>() {
348 let height = N::_CONSENSUS_VERSION_HEIGHTS.first().unwrap().1;
349 assert_eq!(height, 0);
350 let consensus_version = N::_CONSENSUS_VERSION_HEIGHTS.first().unwrap().0;
351 assert_eq!(consensus_version, ConsensusVersion::V1);
352 assert_eq!(consensus_version as usize, 1);
353 }
354
355 fn consensus_versions<N: Network>() {
357 let mut previous_version = N::_CONSENSUS_VERSION_HEIGHTS.first().unwrap().0;
358 assert_eq!(previous_version as usize, 1);
360 for (version, _) in N::_CONSENSUS_VERSION_HEIGHTS.iter().skip(1) {
362 assert_eq!(*version as usize, previous_version as usize + 1);
363 previous_version = *version;
364 }
365 let mut previous_version = N::MAX_CERTIFICATES.first().unwrap().0;
367 for (version, _) in N::MAX_CERTIFICATES.iter().skip(1) {
368 assert!(*version > previous_version);
369 previous_version = *version;
370 }
371 let mut previous_version = N::TRANSACTION_SPEND_LIMIT.first().unwrap().0;
372 for (version, _) in N::TRANSACTION_SPEND_LIMIT.iter().skip(1) {
373 assert!(*version > previous_version);
374 previous_version = *version;
375 }
376 let mut previous_version = N::CREDITS_PER_SECOND_OF_RUNTIME.first().unwrap().0;
377 for (version, _) in N::CREDITS_PER_SECOND_OF_RUNTIME.iter().skip(1) {
378 assert!(*version > previous_version);
379 previous_version = *version;
380 }
381 let mut previous_version = N::MAX_ARRAY_ELEMENTS.first().unwrap().0;
382 for (version, _) in N::MAX_ARRAY_ELEMENTS.iter().skip(1) {
383 assert!(*version > previous_version);
384 previous_version = *version;
385 }
386 let mut previous_version = N::MAX_PROGRAM_SIZE.first().unwrap().0;
387 for (version, _) in N::MAX_PROGRAM_SIZE.iter().skip(1) {
388 assert!(*version > previous_version);
389 previous_version = *version;
390 }
391 let mut previous_version = N::MAX_TRANSACTION_SIZE.first().unwrap().0;
392 for (version, _) in N::MAX_TRANSACTION_SIZE.iter().skip(1) {
393 assert!(*version > previous_version);
394 previous_version = *version;
395 }
396 let mut previous_version = N::MAX_WRITES.first().unwrap().0;
397 for (version, _) in N::MAX_WRITES.iter().skip(1) {
398 assert!(*version > previous_version);
399 previous_version = *version;
400 }
401 let mut previous_version = N::ANCHOR_TIMES.first().unwrap().0;
402 for (version, _) in N::ANCHOR_TIMES.iter().skip(1) {
403 assert!(*version > previous_version);
404 previous_version = *version;
405 }
406 }
407
408 fn consensus_constants_increasing_heights<N: Network>() {
410 let mut previous_height = N::CONSENSUS_VERSION_HEIGHTS().first().unwrap().1;
411 for (version, height) in N::CONSENSUS_VERSION_HEIGHTS().iter().skip(1) {
412 assert!(*height > previous_height);
413 previous_height = *height;
414 assert_eq!(N::CONSENSUS_VERSION(*height).unwrap(), *version);
416 assert_eq!(N::CONSENSUS_HEIGHT(*version).unwrap(), *height);
418 }
419 }
420
421 fn consensus_constants_valid_heights<N: Network>() {
423 for (version, value) in N::MAX_CERTIFICATES.iter() {
424 let height = N::CONSENSUS_VERSION_HEIGHTS().iter().find(|(c_version, _)| *c_version == *version).unwrap().1;
426 assert_eq!(consensus_config_value!(N, MAX_CERTIFICATES, height).unwrap(), *value);
428 }
429 for (version, value) in N::TRANSACTION_SPEND_LIMIT.iter() {
430 let height = N::CONSENSUS_VERSION_HEIGHTS().iter().find(|(c_version, _)| *c_version == *version).unwrap().1;
432 assert_eq!(consensus_config_value!(N, TRANSACTION_SPEND_LIMIT, height).unwrap(), *value);
434 }
435 for (version, value) in N::CREDITS_PER_SECOND_OF_RUNTIME.iter() {
436 let height = N::CONSENSUS_VERSION_HEIGHTS().iter().find(|(c_version, _)| *c_version == *version).unwrap().1;
438 assert_eq!(consensus_config_value!(N, CREDITS_PER_SECOND_OF_RUNTIME, height).unwrap(), *value);
440 }
441 for (version, value) in N::MAX_ARRAY_ELEMENTS.iter() {
442 let height = N::CONSENSUS_VERSION_HEIGHTS().iter().find(|(c_version, _)| *c_version == *version).unwrap().1;
444 assert_eq!(consensus_config_value!(N, MAX_ARRAY_ELEMENTS, height).unwrap(), *value);
446 }
447 for (version, value) in N::MAX_PROGRAM_SIZE.iter() {
448 let height = N::CONSENSUS_VERSION_HEIGHTS().iter().find(|(c_version, _)| *c_version == *version).unwrap().1;
450 assert_eq!(consensus_config_value!(N, MAX_PROGRAM_SIZE, height).unwrap(), *value);
452 }
453 for (version, value) in N::MAX_TRANSACTION_SIZE.iter() {
454 let height = N::CONSENSUS_VERSION_HEIGHTS().iter().find(|(c_version, _)| *c_version == *version).unwrap().1;
456 assert_eq!(consensus_config_value!(N, MAX_TRANSACTION_SIZE, height).unwrap(), *value);
458 }
459 for (version, value) in N::MAX_WRITES.iter() {
460 let height = N::CONSENSUS_VERSION_HEIGHTS().iter().find(|(c_version, _)| *c_version == *version).unwrap().1;
462 assert_eq!(consensus_config_value!(N, MAX_WRITES, height).unwrap(), *value);
464 }
465 for (version, value) in N::ANCHOR_TIMES.iter() {
466 let height = N::CONSENSUS_VERSION_HEIGHTS().iter().find(|(c_version, _)| c_version == version).unwrap().1;
467 assert_eq!(consensus_config_value!(N, ANCHOR_TIMES, height).unwrap(), *value);
468 }
469 }
470
471 fn consensus_config_returns_some<N: Network>() {
473 for (_, height) in N::CONSENSUS_VERSION_HEIGHTS().iter() {
474 assert!(consensus_config_value!(N, MAX_CERTIFICATES, *height).is_some());
475 assert!(consensus_config_value!(N, TRANSACTION_SPEND_LIMIT, *height).is_some());
476 assert!(consensus_config_value!(N, CREDITS_PER_SECOND_OF_RUNTIME, *height).is_some());
477 assert!(consensus_config_value!(N, MAX_ARRAY_ELEMENTS, *height).is_some());
478 assert!(consensus_config_value!(N, MAX_PROGRAM_SIZE, *height).is_some());
479 assert!(consensus_config_value!(N, MAX_TRANSACTION_SIZE, *height).is_some());
480 assert!(consensus_config_value!(N, MAX_WRITES, *height).is_some());
481 assert!(consensus_config_value!(N, ANCHOR_TIMES, *height).is_some());
482 }
483 }
484
485 fn max_certificates_increasing<N: Network>() {
488 let mut previous_value = N::MAX_CERTIFICATES.first().unwrap().1;
489 for (_, value) in N::MAX_CERTIFICATES.iter().skip(1) {
490 assert!(*value >= previous_value);
491 previous_value = *value;
492 }
493 }
494
495 fn max_array_elements_increasing<N: Network>() {
498 let mut previous_value = N::MAX_ARRAY_ELEMENTS.first().unwrap().1;
499 for (_, value) in N::MAX_ARRAY_ELEMENTS.iter().skip(1) {
500 assert!(*value >= previous_value);
501 previous_value = *value;
502 }
503 }
504
505 fn transaction_size_exceeds_program_size<N: Network>() {
508 const MIN_OVERHEAD: usize = 28_000; for (_, height) in N::CONSENSUS_VERSION_HEIGHTS().iter() {
511 let max_program_size = consensus_config_value!(N, MAX_PROGRAM_SIZE, *height).unwrap();
512 let max_transaction_size = consensus_config_value!(N, MAX_TRANSACTION_SIZE, *height).unwrap();
513
514 assert!(
515 max_transaction_size >= max_program_size + MIN_OVERHEAD,
516 "At height {height}: MAX_TRANSACTION_SIZE ({max_transaction_size}) must be at least {MIN_OVERHEAD} bytes greater than MAX_PROGRAM_SIZE ({max_program_size})"
517 );
518 }
519 }
520
521 fn program_and_transaction_size_aligned<N: Network>() {
527 assert_eq!(
529 N::MAX_PROGRAM_SIZE.len(),
530 N::MAX_TRANSACTION_SIZE.len(),
531 "MAX_PROGRAM_SIZE and MAX_TRANSACTION_SIZE must define the same number of entries"
532 );
533 for (index, (program_version, program_size)) in N::MAX_PROGRAM_SIZE.iter().enumerate() {
536 let (transaction_version, transaction_size) = &N::MAX_TRANSACTION_SIZE[index];
537 assert_eq!(
538 program_version, transaction_version,
539 "MAX_PROGRAM_SIZE and MAX_TRANSACTION_SIZE must be keyed by the same consensus version at index {index}, but found {program_version} and {transaction_version}"
540 );
541 assert!(
542 transaction_size > program_size,
543 "At consensus version {program_version}: MAX_TRANSACTION_SIZE ({transaction_size}) must be greater than MAX_PROGRAM_SIZE ({program_size})"
544 );
545 }
546 assert!(
548 N::LATEST_MAX_TRANSACTION_SIZE() > N::LATEST_MAX_PROGRAM_SIZE(),
549 "LATEST_MAX_TRANSACTION_SIZE ({}) must be greater than LATEST_MAX_PROGRAM_SIZE ({})",
550 N::LATEST_MAX_TRANSACTION_SIZE(),
551 N::LATEST_MAX_PROGRAM_SIZE()
552 );
553 }
554
555 fn constants_equal_length<N1: Network, N2: Network, N3: Network>() {
557 let _ = [N1::CONSENSUS_VERSION_HEIGHTS, N2::CONSENSUS_VERSION_HEIGHTS, N3::CONSENSUS_VERSION_HEIGHTS];
559 let _ = [N1::MAX_CERTIFICATES, N2::MAX_CERTIFICATES, N3::MAX_CERTIFICATES];
560 let _ = [N1::TRANSACTION_SPEND_LIMIT, N2::TRANSACTION_SPEND_LIMIT, N3::TRANSACTION_SPEND_LIMIT];
561 let _ =
562 [N1::CREDITS_PER_SECOND_OF_RUNTIME, N2::CREDITS_PER_SECOND_OF_RUNTIME, N3::CREDITS_PER_SECOND_OF_RUNTIME];
563 let _ = [N1::MAX_ARRAY_ELEMENTS, N2::MAX_ARRAY_ELEMENTS, N3::MAX_ARRAY_ELEMENTS];
564 let _ = [N1::MAX_PROGRAM_SIZE, N2::MAX_PROGRAM_SIZE, N3::MAX_PROGRAM_SIZE];
565 let _ = [N1::MAX_TRANSACTION_SIZE, N2::MAX_TRANSACTION_SIZE, N3::MAX_TRANSACTION_SIZE];
566 let _ = [N1::MAX_WRITES, N2::MAX_WRITES, N3::MAX_WRITES];
567 let _ = [N1::ANCHOR_TIMES, N2::ANCHOR_TIMES, N3::ANCHOR_TIMES];
568 }
569
570 fn latest_max_functions_are_safe<N: Network>() {
573 assert!(N::LATEST_MAX_CERTIFICATES() > 0, "LATEST_MAX_CERTIFICATES must be positive");
575 assert!(N::LATEST_MAX_PROGRAM_SIZE() > 0, "LATEST_MAX_PROGRAM_SIZE must be positive");
577 assert!(N::LATEST_MAX_TRANSACTION_SIZE() > 0, "LATEST_MAX_TRANSACTION_SIZE must be positive");
579 assert!(N::LATEST_MAX_WRITES() > 0, "LATEST_MAX_WRITES must be positive");
581 }
582
583 #[test]
584 #[allow(clippy::assertions_on_constants)]
585 fn test_consensus_constants() {
586 consensus_constants_at_genesis::<MainnetV0>();
587 consensus_constants_at_genesis::<TestnetV0>();
588 consensus_constants_at_genesis::<CanaryV0>();
589
590 consensus_versions::<MainnetV0>();
591 consensus_versions::<TestnetV0>();
592 consensus_versions::<CanaryV0>();
593
594 consensus_constants_increasing_heights::<MainnetV0>();
595 consensus_constants_increasing_heights::<TestnetV0>();
596 consensus_constants_increasing_heights::<CanaryV0>();
597
598 consensus_constants_valid_heights::<MainnetV0>();
599 consensus_constants_valid_heights::<TestnetV0>();
600 consensus_constants_valid_heights::<CanaryV0>();
601
602 consensus_config_returns_some::<MainnetV0>();
603 consensus_config_returns_some::<TestnetV0>();
604 consensus_config_returns_some::<CanaryV0>();
605
606 max_certificates_increasing::<MainnetV0>();
607 max_certificates_increasing::<TestnetV0>();
608 max_certificates_increasing::<CanaryV0>();
609
610 max_array_elements_increasing::<MainnetV0>();
611 max_array_elements_increasing::<TestnetV0>();
612 max_array_elements_increasing::<CanaryV0>();
613
614 transaction_size_exceeds_program_size::<MainnetV0>();
615 transaction_size_exceeds_program_size::<TestnetV0>();
616 transaction_size_exceeds_program_size::<CanaryV0>();
617
618 program_and_transaction_size_aligned::<MainnetV0>();
619 program_and_transaction_size_aligned::<TestnetV0>();
620 program_and_transaction_size_aligned::<CanaryV0>();
621
622 latest_max_functions_are_safe::<MainnetV0>();
623 latest_max_functions_are_safe::<TestnetV0>();
624 latest_max_functions_are_safe::<CanaryV0>();
625
626 constants_equal_length::<MainnetV0, TestnetV0, CanaryV0>();
627 }
628
629 #[test]
631 fn test_to_bytes() {
632 let version = ConsensusVersion::V8;
633 let bytes = version.to_bytes_le().unwrap();
634 let result = ConsensusVersion::from_bytes_le(&bytes).unwrap();
635 assert_eq!(result, version);
636
637 let version = ConsensusVersion::latest();
638 let bytes = version.to_bytes_le().unwrap();
639 let result = ConsensusVersion::from_bytes_le(&bytes).unwrap();
640 assert_eq!(result, version);
641
642 let invalid_bytes = u16::MAX.to_bytes_le().unwrap();
643 let result = ConsensusVersion::from_bytes_le(&invalid_bytes);
644 assert!(result.is_err());
645 }
646
647 #[test]
648 fn test_reward_anchor_time() {
649 assert_eq!(MainnetV0::REWARD_ANCHOR_TIME, MainnetV0::ANCHOR_TIMES.first().unwrap().1);
650 assert_eq!(TestnetV0::REWARD_ANCHOR_TIME, TestnetV0::ANCHOR_TIMES.first().unwrap().1);
651 assert_eq!(CanaryV0::REWARD_ANCHOR_TIME, CanaryV0::ANCHOR_TIMES.first().unwrap().1);
652 }
653
654 #[test]
655 fn test_varuna_version_from_consensus() {
656 assert_eq!(varuna_version_from_consensus(ConsensusVersion::V3), VarunaVersion::V1);
658 assert_eq!(varuna_version_from_consensus(ConsensusVersion::V4), VarunaVersion::V2);
659 }
660}