tempo_commonware_node/epoch/
mod.rs1pub(crate) mod manager;
10mod scheme_provider;
11
12use commonware_consensus::types::Epoch;
13pub(crate) use manager::ingress::{Enter, Exit};
14pub(crate) use scheme_provider::SchemeProvider;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub(crate) enum RelativePosition {
19 FirstHalf,
20 Middle,
21 SecondHalf,
22}
23
24pub(crate) fn relative_position(height: u64, epoch_length: u64) -> RelativePosition {
41 let mid_point = epoch_length / 2;
42
43 let height_finite_field = height.rem_euclid(epoch_length);
44
45 match height_finite_field.cmp(&mid_point) {
46 std::cmp::Ordering::Less => RelativePosition::FirstHalf,
47 std::cmp::Ordering::Equal => RelativePosition::Middle,
48 std::cmp::Ordering::Greater => RelativePosition::SecondHalf,
49 }
50}
51
52pub(crate) fn is_first_block_in_epoch(epoch_length: u64, height: u64) -> Option<Epoch> {
58 height
61 .is_multiple_of(epoch_length)
62 .then(|| commonware_consensus::utils::epoch(epoch_length, height))
63}
64
65#[cfg(test)]
66mod tests {
67 use crate::epoch::is_first_block_in_epoch;
68
69 use super::{RelativePosition, relative_position};
70
71 #[track_caller]
72 fn assert_relative_position(expected: RelativePosition, height: u64, epoch_length: u64) {
73 assert_eq!(expected, relative_position(height, epoch_length),);
74 }
75
76 #[test]
77 fn height_falls_into_correct_part_of_epoch() {
78 use RelativePosition::*;
79
80 assert_relative_position(FirstHalf, 0, 100);
81 assert_relative_position(FirstHalf, 1, 100);
82 assert_relative_position(Middle, 50, 100);
83 assert_relative_position(SecondHalf, 51, 100);
84 assert_relative_position(SecondHalf, 99, 100);
85
86 assert_relative_position(FirstHalf, 100, 100);
87 assert_relative_position(FirstHalf, 101, 100);
88 assert_relative_position(Middle, 150, 100);
89 assert_relative_position(SecondHalf, 151, 100);
90 assert_relative_position(SecondHalf, 199, 100);
91
92 assert_relative_position(FirstHalf, 200, 100);
93
94 assert_relative_position(FirstHalf, 0, 99);
95 assert_relative_position(FirstHalf, 1, 99);
96 assert_relative_position(Middle, 49, 99);
97 assert_relative_position(SecondHalf, 50, 99);
98 assert_relative_position(SecondHalf, 51, 99);
99 assert_relative_position(SecondHalf, 98, 99);
100
101 assert_relative_position(FirstHalf, 99, 99);
102 assert_relative_position(FirstHalf, 100, 99);
103 assert_relative_position(Middle, 148, 99);
104 assert_relative_position(SecondHalf, 149, 99);
105 assert_relative_position(SecondHalf, 197, 99);
106
107 assert_relative_position(FirstHalf, 198, 99);
108
109 assert_relative_position(FirstHalf, 9, 199);
110 assert_relative_position(FirstHalf, 1, 199);
111 assert_relative_position(Middle, 99, 199);
112 assert_relative_position(SecondHalf, 100, 199);
113 assert_relative_position(SecondHalf, 101, 199);
114 assert_relative_position(SecondHalf, 198, 199);
115
116 assert_relative_position(FirstHalf, 199, 199);
117 }
118
119 #[should_panic]
120 #[test]
121 fn is_first_block_in_epoch_panics_on_epoch_length_0_height_0() {
122 is_first_block_in_epoch(0, 0);
123 }
124
125 #[test]
126 fn is_first_block_in_epoch_identifies_first_block() {
127 assert_eq!(is_first_block_in_epoch(10, 0), Some(0));
128 assert_eq!(is_first_block_in_epoch(10, 10), Some(1));
129 assert_eq!(is_first_block_in_epoch(10, 20), Some(2));
130 assert_eq!(is_first_block_in_epoch(5, 215), Some(43));
131 }
132
133 #[test]
134 fn is_first_block_in_epoch_returns_none_when_not_first_block() {
135 assert_eq!(is_first_block_in_epoch(10, 1), None);
136 assert_eq!(is_first_block_in_epoch(10, 9), None);
137 assert_eq!(is_first_block_in_epoch(10, 18), None);
138 }
139}