consensus_core/
context.rs1use std::{sync::Arc, time::SystemTime};
6
7use consensus_config::{AuthorityIndex, Committee, Parameters};
8#[cfg(test)]
9use consensus_config::{NetworkKeyPair, ProtocolKeyPair};
10use iota_protocol_config::ProtocolConfig;
11#[cfg(test)]
12use tempfile::TempDir;
13use tokio::time::Instant;
14
15#[cfg(test)]
16use crate::metrics::test_metrics;
17use crate::{block::BlockTimestampMs, metrics::Metrics};
18#[derive(Clone)]
21pub(crate) struct Context {
22 pub epoch_start_timestamp_ms: u64,
24 pub own_index: AuthorityIndex,
26 pub committee: Committee,
28 pub parameters: Parameters,
30 pub protocol_config: ProtocolConfig,
32 pub metrics: Arc<Metrics>,
34 pub clock: Arc<Clock>,
36}
37
38impl Context {
39 pub(crate) fn new(
40 epoch_start_timestamp_ms: u64,
41 own_index: AuthorityIndex,
42 committee: Committee,
43 parameters: Parameters,
44 protocol_config: ProtocolConfig,
45 metrics: Arc<Metrics>,
46 clock: Arc<Clock>,
47 ) -> Self {
48 Self {
49 epoch_start_timestamp_ms,
50 own_index,
51 committee,
52 parameters,
53 protocol_config,
54 metrics,
55 clock,
56 }
57 }
58
59 #[cfg(test)]
61 pub(crate) fn new_for_test(
62 committee_size: usize,
63 ) -> (Self, Vec<(NetworkKeyPair, ProtocolKeyPair)>) {
64 let (committee, keypairs) =
65 consensus_config::local_committee_and_keys(0, vec![1; committee_size]);
66 let metrics = test_metrics(committee_size);
67 let temp_dir = TempDir::new().unwrap();
68 let clock = Arc::new(Clock::default());
69
70 let context = Context::new(
71 0,
72 AuthorityIndex::new_for_test(0),
73 committee,
74 Parameters {
75 db_path: temp_dir.keep(),
76 ..Default::default()
77 },
78 ProtocolConfig::get_for_max_version_UNSAFE(),
79 metrics,
80 clock,
81 );
82 (context, keypairs)
83 }
84
85 #[cfg(test)]
86 pub(crate) fn with_epoch_start_timestamp_ms(mut self, epoch_start_timestamp_ms: u64) -> Self {
87 self.epoch_start_timestamp_ms = epoch_start_timestamp_ms;
88 self
89 }
90
91 #[cfg(test)]
92 pub(crate) fn with_authority_index(mut self, authority: AuthorityIndex) -> Self {
93 self.own_index = authority;
94 self
95 }
96
97 #[cfg(test)]
98 pub(crate) fn with_committee(mut self, committee: Committee) -> Self {
99 self.committee = committee;
100 self
101 }
102
103 #[cfg(test)]
104 pub(crate) fn with_parameters(mut self, parameters: Parameters) -> Self {
105 self.parameters = parameters;
106 self
107 }
108}
109
110pub struct Clock {
117 initial_instant: Instant,
118 initial_system_time: SystemTime,
119 #[cfg(any(test, msim))]
121 clock_drift: BlockTimestampMs,
122}
123
124impl Default for Clock {
125 fn default() -> Self {
126 Self {
127 initial_instant: Instant::now(),
128 initial_system_time: SystemTime::now(),
129 #[cfg(any(test, msim))]
130 clock_drift: 0,
131 }
132 }
133}
134
135impl Clock {
136 #[cfg(any(test, msim))]
137 pub fn new_for_test(clock_drift: BlockTimestampMs) -> Self {
138 Self {
139 initial_instant: Instant::now(),
140 initial_system_time: SystemTime::now(),
141 clock_drift,
142 }
143 }
144
145 pub(crate) fn timestamp_utc_ms(&self) -> BlockTimestampMs {
149 let now: Instant = Instant::now();
150 let monotonic_system_time = self
151 .initial_system_time
152 .checked_add(
153 now.checked_duration_since(self.initial_instant)
154 .unwrap_or_else(|| {
155 panic!(
156 "current instant ({:?}) < initial instant ({:?})",
157 now, self.initial_instant
158 )
159 }),
160 )
161 .expect("Computing system time should not overflow");
162 let timestamp = monotonic_system_time
163 .duration_since(SystemTime::UNIX_EPOCH)
164 .unwrap_or_else(|_| {
165 panic!(
166 "system time ({:?}) < UNIX_EPOCH ({:?})",
167 monotonic_system_time,
168 SystemTime::UNIX_EPOCH,
169 )
170 })
171 .as_millis() as BlockTimestampMs;
172
173 #[cfg(any(test, msim))]
177 {
178 timestamp + self.clock_drift
179 }
180 #[cfg(not(any(test, msim)))]
181 {
182 timestamp
183 }
184 }
185}