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