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::{
18 block::BlockTimestampMs, metrics::Metrics, scoring_metrics_store::MysticetiScoringMetricsStore,
19};
20#[derive(Clone)]
23pub(crate) struct Context {
24 pub epoch_start_timestamp_ms: u64,
26 pub own_index: AuthorityIndex,
28 pub committee: Committee,
30 pub parameters: Parameters,
32 pub protocol_config: ProtocolConfig,
34 pub metrics: Arc<Metrics>,
36 pub(crate) scoring_metrics_store: Arc<MysticetiScoringMetricsStore>,
38 pub clock: Arc<Clock>,
40}
41
42impl Context {
43 pub(crate) fn new(
44 epoch_start_timestamp_ms: u64,
45 own_index: AuthorityIndex,
46 committee: Committee,
47 parameters: Parameters,
48 protocol_config: ProtocolConfig,
49 metrics: Arc<Metrics>,
50 scoring_metrics_store: Arc<MysticetiScoringMetricsStore>,
51
52 clock: Arc<Clock>,
53 ) -> Self {
54 Self {
55 epoch_start_timestamp_ms,
56 own_index,
57 committee,
58 parameters,
59 protocol_config,
60 metrics,
61 scoring_metrics_store,
62 clock,
63 }
64 }
65
66 #[cfg(test)]
68 pub(crate) fn new_for_test(
69 committee_size: usize,
70 ) -> (Self, Vec<(NetworkKeyPair, ProtocolKeyPair)>) {
71 use iota_common::scoring_metrics::{ScoringMetricsV1, VersionedScoringMetrics};
72
73 let (committee, keypairs) =
74 consensus_config::local_committee_and_keys(0, vec![1; committee_size]);
75 let metrics = test_metrics();
76 let temp_dir = TempDir::new().unwrap();
77 let clock = Arc::new(Clock::default());
78 let current_local_metrics_count = Arc::new(VersionedScoringMetrics::V1(
79 ScoringMetricsV1::new(committee_size),
80 ));
81 let scoring_metrics_store = Arc::new(MysticetiScoringMetricsStore::new(
82 committee_size,
83 current_local_metrics_count,
84 &ProtocolConfig::get_for_max_version_UNSAFE(),
85 ));
86 let context = Context::new(
87 0,
88 AuthorityIndex::new_for_test(0),
89 committee,
90 Parameters {
91 db_path: temp_dir.keep(),
92 ..Default::default()
93 },
94 ProtocolConfig::get_for_max_version_UNSAFE(),
95 metrics,
96 scoring_metrics_store,
97 clock,
98 );
99 (context, keypairs)
100 }
101
102 #[cfg(test)]
103 pub(crate) fn with_epoch_start_timestamp_ms(mut self, epoch_start_timestamp_ms: u64) -> Self {
104 self.epoch_start_timestamp_ms = epoch_start_timestamp_ms;
105 self
106 }
107
108 #[cfg(test)]
109 pub(crate) fn with_authority_index(mut self, authority: AuthorityIndex) -> Self {
110 self.own_index = authority;
111 self
112 }
113
114 #[cfg(test)]
115 pub(crate) fn with_committee(mut self, committee: Committee) -> Self {
116 self.committee = committee;
117 self
118 }
119
120 #[cfg(test)]
121 pub(crate) fn with_parameters(mut self, parameters: Parameters) -> Self {
122 self.parameters = parameters;
123 self
124 }
125}
126
127pub struct Clock {
134 initial_instant: Instant,
135 initial_system_time: SystemTime,
136 #[cfg(any(test, msim))]
138 clock_drift: BlockTimestampMs,
139}
140
141impl Default for Clock {
142 fn default() -> Self {
143 Self {
144 initial_instant: Instant::now(),
145 initial_system_time: SystemTime::now(),
146 #[cfg(any(test, msim))]
147 clock_drift: 0,
148 }
149 }
150}
151
152impl Clock {
153 #[cfg(any(test, msim))]
154 pub fn new_for_test(clock_drift: BlockTimestampMs) -> Self {
155 Self {
156 initial_instant: Instant::now(),
157 initial_system_time: SystemTime::now(),
158 clock_drift,
159 }
160 }
161
162 pub(crate) fn timestamp_utc_ms(&self) -> BlockTimestampMs {
166 let now: Instant = Instant::now();
167 let monotonic_system_time = self
168 .initial_system_time
169 .checked_add(
170 now.checked_duration_since(self.initial_instant)
171 .unwrap_or_else(|| {
172 panic!(
173 "current instant ({:?}) < initial instant ({:?})",
174 now, self.initial_instant
175 )
176 }),
177 )
178 .expect("Computing system time should not overflow");
179 let timestamp = monotonic_system_time
180 .duration_since(SystemTime::UNIX_EPOCH)
181 .unwrap_or_else(|_| {
182 panic!(
183 "system time ({:?}) < UNIX_EPOCH ({:?})",
184 monotonic_system_time,
185 SystemTime::UNIX_EPOCH,
186 )
187 })
188 .as_millis() as BlockTimestampMs;
189
190 #[cfg(any(test, msim))]
194 {
195 timestamp + self.clock_drift
196 }
197 #[cfg(not(any(test, msim)))]
198 {
199 timestamp
200 }
201 }
202}