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