miraland_program/clock.rs
1//! Information about the network's clock, ticks, slots, etc.
2//!
3//! Time in Miraland is marked primarily by _slots_, which occur approximately every
4//! 400 milliseconds, and are numbered sequentially. For every slot, a leader is
5//! chosen from the validator set, and that leader is expected to produce a new
6//! block, though sometimes leaders may fail to do so. Blocks can be identified
7//! by their slot number, and some slots do not contain a block.
8//!
9//! An approximation of the passage of real-world time can be calculated by
10//! multiplying a number of slots by [`DEFAULT_MS_PER_SLOT`], which is a constant target
11//! time for the network to produce slots. Note though that this method suffers
12//! a variable amount of drift, as the network does not produce slots at exactly
13//! the target rate, and the greater number of slots being calculated for, the
14//! greater the drift. Epochs cannot be used this way as they contain variable
15//! numbers of slots.
16//!
17//! The network's current view of the real-world time can always be accessed via
18//! [`Clock::unix_timestamp`], which is produced by an [oracle derived from the
19//! validator set][oracle].
20//!
21//! [oracle]: https://docs.solana.com/implemented-proposals/validator-timestamp-oracle
22
23use miraland_sdk_macro::CloneZeroed;
24
25/// The default tick rate that the cluster attempts to achieve (160 per second).
26///
27/// Note that the actual tick rate at any given time should be expected to drift.
28pub const DEFAULT_TICKS_PER_SECOND: u64 = 160;
29
30#[cfg(test)]
31static_assertions::const_assert_eq!(MS_PER_TICK, 6);
32
33/// The number of milliseconds per tick (6).
34pub const MS_PER_TICK: u64 = 1000 / DEFAULT_TICKS_PER_SECOND;
35
36#[deprecated(since = "1.15.0", note = "Please use DEFAULT_MS_PER_SLOT instead")]
37/// The expected duration of a slot (400 milliseconds).
38pub const SLOT_MS: u64 = DEFAULT_MS_PER_SLOT;
39
40// At 160 ticks/s, 64 ticks per slot implies that leader rotation and voting will happen
41// every 400 ms. A fast voting cadence ensures faster finality and convergence
42pub const DEFAULT_TICKS_PER_SLOT: u64 = 64;
43
44// GCP n1-standard hardware and also a xeon e5-2520 v4 are about this rate of hashes/s
45pub const DEFAULT_HASHES_PER_SECOND: u64 = 2_000_000;
46
47// Empirical sampling of mainnet validator hash rate showed the following stake
48// percentages can exceed the designated hash rates as of July 2023:
49// 97.6%
50pub const UPDATED_HASHES_PER_SECOND_2: u64 = 2_800_000;
51// 96.2%
52pub const UPDATED_HASHES_PER_SECOND_3: u64 = 4_400_000;
53// 96.2%
54pub const UPDATED_HASHES_PER_SECOND_4: u64 = 7_600_000;
55// 96.2%
56pub const UPDATED_HASHES_PER_SECOND_5: u64 = 9_200_000;
57// 96.2%
58pub const UPDATED_HASHES_PER_SECOND_6: u64 = 10_000_000;
59
60#[cfg(test)]
61static_assertions::const_assert_eq!(DEFAULT_HASHES_PER_TICK, 12_500);
62pub const DEFAULT_HASHES_PER_TICK: u64 = DEFAULT_HASHES_PER_SECOND / DEFAULT_TICKS_PER_SECOND;
63
64#[cfg(test)]
65static_assertions::const_assert_eq!(UPDATED_HASHES_PER_TICK2, 17_500);
66pub const UPDATED_HASHES_PER_TICK2: u64 = UPDATED_HASHES_PER_SECOND_2 / DEFAULT_TICKS_PER_SECOND;
67
68#[cfg(test)]
69static_assertions::const_assert_eq!(UPDATED_HASHES_PER_TICK3, 27_500);
70pub const UPDATED_HASHES_PER_TICK3: u64 = UPDATED_HASHES_PER_SECOND_3 / DEFAULT_TICKS_PER_SECOND;
71
72#[cfg(test)]
73static_assertions::const_assert_eq!(UPDATED_HASHES_PER_TICK4, 47_500);
74pub const UPDATED_HASHES_PER_TICK4: u64 = UPDATED_HASHES_PER_SECOND_4 / DEFAULT_TICKS_PER_SECOND;
75
76#[cfg(test)]
77static_assertions::const_assert_eq!(UPDATED_HASHES_PER_TICK5, 57_500);
78pub const UPDATED_HASHES_PER_TICK5: u64 = UPDATED_HASHES_PER_SECOND_5 / DEFAULT_TICKS_PER_SECOND;
79
80#[cfg(test)]
81static_assertions::const_assert_eq!(UPDATED_HASHES_PER_TICK6, 62_500);
82pub const UPDATED_HASHES_PER_TICK6: u64 = UPDATED_HASHES_PER_SECOND_6 / DEFAULT_TICKS_PER_SECOND;
83
84// 1 Dev Epoch = 400 ms * 8192 ~= 55 minutes
85pub const DEFAULT_DEV_SLOTS_PER_EPOCH: u64 = 8192;
86
87#[cfg(test)]
88static_assertions::const_assert_eq!(SECONDS_PER_DAY, 86_400);
89pub const SECONDS_PER_DAY: u64 = 24 * 60 * 60;
90
91#[cfg(test)]
92static_assertions::const_assert_eq!(TICKS_PER_DAY, 13_824_000);
93pub const TICKS_PER_DAY: u64 = DEFAULT_TICKS_PER_SECOND * SECONDS_PER_DAY;
94
95#[cfg(test)]
96static_assertions::const_assert_eq!(DEFAULT_SLOTS_PER_EPOCH, 432_000);
97
98/// The number of slots per epoch after initial network warmup.
99///
100/// 1 Epoch ~= 2 days.
101pub const DEFAULT_SLOTS_PER_EPOCH: u64 = 2 * TICKS_PER_DAY / DEFAULT_TICKS_PER_SLOT;
102
103// leader schedule is governed by this
104pub const NUM_CONSECUTIVE_LEADER_SLOTS: u64 = 4;
105
106#[cfg(test)]
107static_assertions::const_assert_eq!(DEFAULT_MS_PER_SLOT, 400);
108/// The expected duration of a slot (400 milliseconds).
109pub const DEFAULT_MS_PER_SLOT: u64 = 1_000 * DEFAULT_TICKS_PER_SLOT / DEFAULT_TICKS_PER_SECOND;
110pub const DEFAULT_S_PER_SLOT: f64 = DEFAULT_TICKS_PER_SLOT as f64 / DEFAULT_TICKS_PER_SECOND as f64;
111
112/// The time window of recent block hash values over which the bank will track
113/// signatures.
114///
115/// Once the bank discards a block hash, it will reject any transactions that
116/// use that `recent_blockhash` in a transaction. Lowering this value reduces
117/// memory consumption, but requires a client to update its `recent_blockhash`
118/// more frequently. Raising the value lengthens the time a client must wait to
119/// be certain a missing transaction will not be processed by the network.
120pub const MAX_HASH_AGE_IN_SECONDS: usize = 120;
121
122#[cfg(test)]
123static_assertions::const_assert_eq!(MAX_RECENT_BLOCKHASHES, 300);
124// Number of maximum recent blockhashes (one blockhash per non-skipped slot)
125pub const MAX_RECENT_BLOCKHASHES: usize =
126 MAX_HASH_AGE_IN_SECONDS * DEFAULT_TICKS_PER_SECOND as usize / DEFAULT_TICKS_PER_SLOT as usize;
127
128#[cfg(test)]
129static_assertions::const_assert_eq!(MAX_PROCESSING_AGE, 150);
130// The maximum age of a blockhash that will be accepted by the leader
131pub const MAX_PROCESSING_AGE: usize = MAX_RECENT_BLOCKHASHES / 2;
132
133/// This is maximum time consumed in forwarding a transaction from one node to next, before
134/// it can be processed in the target node
135pub const MAX_TRANSACTION_FORWARDING_DELAY_GPU: usize = 2;
136
137/// More delay is expected if CUDA is not enabled (as signature verification takes longer)
138pub const MAX_TRANSACTION_FORWARDING_DELAY: usize = 6;
139
140/// Transaction forwarding, which leader to forward to and how long to hold
141pub const FORWARD_TRANSACTIONS_TO_LEADER_AT_SLOT_OFFSET: u64 = 2;
142pub const HOLD_TRANSACTIONS_SLOT_OFFSET: u64 = 20;
143
144/// The unit of time given to a leader for encoding a block.
145///
146/// It is some some number of _ticks_ long.
147pub type Slot = u64;
148
149/// Uniquely distinguishes every version of a slot.
150///
151/// The `BankId` is unique even if the slot number of two different slots is the
152/// same. This can happen in the case of e.g. duplicate slots.
153pub type BankId = u64;
154
155/// The unit of time a given leader schedule is honored.
156///
157/// It lasts for some number of [`Slot`]s.
158pub type Epoch = u64;
159
160pub const GENESIS_EPOCH: Epoch = 0;
161// must be sync with Account::rent_epoch::default()
162pub const INITIAL_RENT_EPOCH: Epoch = 0;
163
164/// An index to the slots of a epoch.
165pub type SlotIndex = u64;
166
167/// The number of slots in a epoch.
168pub type SlotCount = u64;
169
170/// An approximate measure of real-world time.
171///
172/// Expressed as Unix time (i.e. seconds since the Unix epoch).
173pub type UnixTimestamp = i64;
174
175/// A representation of network time.
176///
177/// All members of `Clock` start from 0 upon network boot.
178#[repr(C)]
179#[derive(Serialize, Deserialize, Debug, CloneZeroed, Default, PartialEq, Eq)]
180pub struct Clock {
181 /// The current `Slot`.
182 pub slot: Slot,
183 /// The timestamp of the first `Slot` in this `Epoch`.
184 pub epoch_start_timestamp: UnixTimestamp,
185 /// The current `Epoch`.
186 pub epoch: Epoch,
187 /// The future `Epoch` for which the leader schedule has
188 /// most recently been calculated.
189 pub leader_schedule_epoch: Epoch,
190 /// The approximate real world time of the current slot.
191 ///
192 /// This value was originally computed from genesis creation time and
193 /// network time in slots, incurring a lot of drift. Following activation of
194 /// the [`timestamp_correction` and `timestamp_bounding`][tsc] features it
195 /// is calculated using a [validator timestamp oracle][oracle].
196 ///
197 /// [tsc]: https://docs.solana.com/implemented-proposals/bank-timestamp-correction
198 /// [oracle]: https://docs.solana.com/implemented-proposals/validator-timestamp-oracle
199 pub unix_timestamp: UnixTimestamp,
200}
201
202#[cfg(test)]
203mod tests {
204 use super::*;
205
206 #[test]
207 fn test_clone() {
208 let clock = Clock {
209 slot: 1,
210 epoch_start_timestamp: 2,
211 epoch: 3,
212 leader_schedule_epoch: 4,
213 unix_timestamp: 5,
214 };
215 let cloned_clock = clock.clone();
216 assert_eq!(cloned_clock, clock);
217 }
218}