Skip to main content

solana_clock/
lib.rs

1//! Information about the network's clock, ticks, slots, etc.
2//!
3//! Time in Solana is marked primarily by _slots_, which are numbered sequentially.
4//! For every slot, a leader is chosen from the validator set, and that leader is
5//! expected to produce a new block, though sometimes leaders may fail to do so.
6//! Blocks can be identified by their slot number, and some slots do not contain a
7//! 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 the SDK's
11//! default target time for the network to produce slots. Note though that this
12//! method suffers a variable amount of drift, as the network does not produce
13//! slots at exactly the target rate. Furthermore, the effective target is changed
14//! dynamically by [SIMD-0525], so clients that require the cluster's current value
15//! must not assume the SDK default reflects the cluster.
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.solanalabs.com/implemented-proposals/validator-timestamp-oracle
22//! [SIMD-0525]: https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0525-reduce-slot-times.md
23#![no_std]
24#![cfg_attr(docsrs, feature(doc_cfg))]
25
26#[cfg(feature = "sysvar")]
27pub mod sysvar;
28
29#[cfg(feature = "serde")]
30use serde_derive::{Deserialize, Serialize};
31use solana_sdk_macro::CloneZeroed;
32
33/// The number of ticks in a slot.
34pub const DEFAULT_TICKS_PER_SLOT: u64 = 64;
35
36pub const DEFAULT_NS_PER_SLOT_400_MS: u64 = 400_000_000;
37pub const DEFAULT_NS_PER_SLOT_350_MS: u64 = 350_000_000;
38pub const DEFAULT_NS_PER_SLOT_300_MS: u64 = 300_000_000;
39pub const DEFAULT_NS_PER_SLOT_250_MS: u64 = 250_000_000;
40pub const DEFAULT_NS_PER_SLOT_200_MS: u64 = 200_000_000;
41
42/// The SDK's default expected duration of a slot, in nanoseconds.
43pub const DEFAULT_NS_PER_SLOT: u64 = DEFAULT_NS_PER_SLOT_300_MS;
44
45pub const DEFAULT_NS_PER_TICK_400_MS: u64 = DEFAULT_NS_PER_SLOT_400_MS / DEFAULT_TICKS_PER_SLOT;
46pub const DEFAULT_NS_PER_TICK_350_MS: u64 = DEFAULT_NS_PER_SLOT_350_MS / DEFAULT_TICKS_PER_SLOT;
47pub const DEFAULT_NS_PER_TICK_300_MS: u64 = DEFAULT_NS_PER_SLOT_300_MS / DEFAULT_TICKS_PER_SLOT;
48pub const DEFAULT_NS_PER_TICK_250_MS: u64 = DEFAULT_NS_PER_SLOT_250_MS / DEFAULT_TICKS_PER_SLOT;
49pub const DEFAULT_NS_PER_TICK_200_MS: u64 = DEFAULT_NS_PER_SLOT_200_MS / DEFAULT_TICKS_PER_SLOT;
50
51/// The default duration of a tick, in nanoseconds.
52pub const DEFAULT_NS_PER_TICK: u64 = DEFAULT_NS_PER_TICK_300_MS;
53
54/// Whole ticks per second at each target slot time.
55///
56/// Values which are not integral are rounded down. Prefer the corresponding
57/// `DEFAULT_NS_PER_TICK_*` constant when an exact duration is required.
58pub const DEFAULT_TICKS_PER_SECOND_400_MS: u64 = 1_000_000_000 / DEFAULT_NS_PER_TICK_400_MS;
59pub const DEFAULT_TICKS_PER_SECOND_350_MS: u64 = 1_000_000_000 / DEFAULT_NS_PER_TICK_350_MS;
60pub const DEFAULT_TICKS_PER_SECOND_300_MS: u64 = 1_000_000_000 / DEFAULT_NS_PER_TICK_300_MS;
61pub const DEFAULT_TICKS_PER_SECOND_250_MS: u64 = 1_000_000_000 / DEFAULT_NS_PER_TICK_250_MS;
62pub const DEFAULT_TICKS_PER_SECOND_200_MS: u64 = 1_000_000_000 / DEFAULT_NS_PER_TICK_200_MS;
63
64/// The default whole-number tick rate (213 per second).
65///
66/// Note that the exact 300 millisecond target is 213 1/3 ticks per second and
67/// that the actual tick rate at any given time should be expected to drift.
68pub const DEFAULT_TICKS_PER_SECOND: u64 = DEFAULT_TICKS_PER_SECOND_300_MS;
69
70#[cfg(test)]
71static_assertions::const_assert_eq!(MS_PER_TICK, 4);
72
73pub const MS_PER_TICK_400_MS: u64 = DEFAULT_NS_PER_TICK_400_MS / 1_000_000;
74pub const MS_PER_TICK_350_MS: u64 = DEFAULT_NS_PER_TICK_350_MS / 1_000_000;
75pub const MS_PER_TICK_300_MS: u64 = DEFAULT_NS_PER_TICK_300_MS / 1_000_000;
76pub const MS_PER_TICK_250_MS: u64 = DEFAULT_NS_PER_TICK_250_MS / 1_000_000;
77pub const MS_PER_TICK_200_MS: u64 = DEFAULT_NS_PER_TICK_200_MS / 1_000_000;
78
79/// The number of whole milliseconds per tick (4).
80///
81/// This value is rounded down. Use [`DEFAULT_NS_PER_TICK`] for the exact target.
82pub const MS_PER_TICK: u64 = MS_PER_TICK_300_MS;
83
84pub const DEFAULT_HASHES_PER_SECOND: u64 = 10_000_000;
85
86#[cfg(test)]
87static_assertions::const_assert_eq!(DEFAULT_HASHES_PER_TICK, 46_875);
88pub const DEFAULT_HASHES_PER_TICK_400_MS: u64 = 62_500;
89pub const DEFAULT_HASHES_PER_TICK_350_MS: u64 = 54_687;
90pub const DEFAULT_HASHES_PER_TICK_300_MS: u64 = 46_875;
91pub const DEFAULT_HASHES_PER_TICK_250_MS: u64 = 39_062;
92pub const DEFAULT_HASHES_PER_TICK_200_MS: u64 = 31_250;
93pub const DEFAULT_HASHES_PER_TICK: u64 = DEFAULT_HASHES_PER_TICK_300_MS;
94
95// 1 Dev Epoch = 300 ms * 8192 ~= 41 minutes
96pub const DEFAULT_DEV_SLOTS_PER_EPOCH: u64 = 8192;
97
98#[cfg(test)]
99static_assertions::const_assert_eq!(SECONDS_PER_DAY, 86_400);
100pub const SECONDS_PER_DAY: u64 = 24 * 60 * 60;
101
102#[cfg(test)]
103static_assertions::const_assert_eq!(TICKS_PER_DAY, 18_432_000);
104pub const TICKS_PER_DAY_400_MS: u64 = SECONDS_PER_DAY * 1_000_000_000 / DEFAULT_NS_PER_TICK_400_MS;
105pub const TICKS_PER_DAY_350_MS: u64 = SECONDS_PER_DAY * 1_000_000_000 / DEFAULT_NS_PER_TICK_350_MS;
106pub const TICKS_PER_DAY_300_MS: u64 = SECONDS_PER_DAY * 1_000_000_000 / DEFAULT_NS_PER_TICK_300_MS;
107pub const TICKS_PER_DAY_250_MS: u64 = SECONDS_PER_DAY * 1_000_000_000 / DEFAULT_NS_PER_TICK_250_MS;
108pub const TICKS_PER_DAY_200_MS: u64 = SECONDS_PER_DAY * 1_000_000_000 / DEFAULT_NS_PER_TICK_200_MS;
109pub const TICKS_PER_DAY: u64 = TICKS_PER_DAY_300_MS;
110
111/// The number of slots per epoch after initial network warmup.
112///
113/// At the default 300 millisecond slot time, one epoch is approximately 36 hours.
114pub const DEFAULT_SLOTS_PER_EPOCH: u64 = 432_000;
115
116#[cfg(test)]
117static_assertions::const_assert_eq!(DEFAULT_MS_PER_SLOT, 300);
118pub const DEFAULT_MS_PER_SLOT_400_MS: u64 = DEFAULT_NS_PER_SLOT_400_MS / 1_000_000;
119pub const DEFAULT_MS_PER_SLOT_350_MS: u64 = DEFAULT_NS_PER_SLOT_350_MS / 1_000_000;
120pub const DEFAULT_MS_PER_SLOT_300_MS: u64 = DEFAULT_NS_PER_SLOT_300_MS / 1_000_000;
121pub const DEFAULT_MS_PER_SLOT_250_MS: u64 = DEFAULT_NS_PER_SLOT_250_MS / 1_000_000;
122pub const DEFAULT_MS_PER_SLOT_200_MS: u64 = DEFAULT_NS_PER_SLOT_200_MS / 1_000_000;
123
124/// The SDK's default expected duration of a slot (300 milliseconds).
125pub const DEFAULT_MS_PER_SLOT: u64 = DEFAULT_MS_PER_SLOT_300_MS;
126
127pub const DEFAULT_S_PER_SLOT_400_MS: f64 = DEFAULT_MS_PER_SLOT_400_MS as f64 / 1_000.0;
128pub const DEFAULT_S_PER_SLOT_350_MS: f64 = DEFAULT_MS_PER_SLOT_350_MS as f64 / 1_000.0;
129pub const DEFAULT_S_PER_SLOT_300_MS: f64 = DEFAULT_MS_PER_SLOT_300_MS as f64 / 1_000.0;
130pub const DEFAULT_S_PER_SLOT_250_MS: f64 = DEFAULT_MS_PER_SLOT_250_MS as f64 / 1_000.0;
131pub const DEFAULT_S_PER_SLOT_200_MS: f64 = DEFAULT_MS_PER_SLOT_200_MS as f64 / 1_000.0;
132pub const DEFAULT_S_PER_SLOT: f64 = DEFAULT_S_PER_SLOT_300_MS;
133
134/// The time window of recent block hash values over which the bank will track
135/// signatures.
136///
137/// Once the bank discards a block hash, it will reject any transactions that
138/// use that `recent_blockhash` in a transaction. Lowering this value reduces
139/// memory consumption, but requires a client to update its `recent_blockhash`
140/// more frequently. Raising the value lengthens the time a client must wait to
141/// be certain a missing transaction will not be processed by the network.
142pub const MAX_HASH_AGE_IN_SECONDS_400_MS: usize = 120;
143pub const MAX_HASH_AGE_IN_SECONDS_350_MS: usize = 105;
144pub const MAX_HASH_AGE_IN_SECONDS_300_MS: usize = 90;
145pub const MAX_HASH_AGE_IN_SECONDS_250_MS: usize = 75;
146pub const MAX_HASH_AGE_IN_SECONDS_200_MS: usize = 60;
147pub const MAX_HASH_AGE_IN_SECONDS: usize = MAX_HASH_AGE_IN_SECONDS_300_MS;
148
149// Maximum number of recent blockhashes (one blockhash per non-skipped slot).
150pub const MAX_RECENT_BLOCKHASHES: usize = 300;
151
152#[cfg(test)]
153static_assertions::const_assert_eq!(MAX_PROCESSING_AGE, 150);
154// The maximum age of a blockhash that will be accepted by the leader
155pub const MAX_PROCESSING_AGE: usize = MAX_RECENT_BLOCKHASHES / 2;
156
157/// This is maximum time consumed in forwarding a transaction from one node to next, before
158/// it can be processed in the target node
159pub const MAX_TRANSACTION_FORWARDING_DELAY_GPU: usize = 2;
160
161/// More delay is expected if CUDA is not enabled (as signature verification takes longer)
162pub const MAX_TRANSACTION_FORWARDING_DELAY: usize = 6;
163
164/// Transaction forwarding, which leader to forward to and how long to hold
165pub const FORWARD_TRANSACTIONS_TO_LEADER_AT_SLOT_OFFSET: u64 = 2;
166pub const HOLD_TRANSACTIONS_SLOT_OFFSET: u64 = 20;
167
168/// The unit of time given to a leader for encoding a block.
169///
170/// It is some number of _ticks_ long.
171pub type Slot = u64;
172
173/// Uniquely distinguishes every version of a slot.
174///
175/// The `BankId` is unique even if the slot number of two different slots is the
176/// same. This can happen in the case of e.g. duplicate slots.
177pub type BankId = u64;
178
179/// The unit of time a given leader schedule is honored.
180///
181/// It lasts for some number of [`Slot`]s.
182pub type Epoch = u64;
183
184pub const GENESIS_EPOCH: Epoch = 0;
185// must be sync with Account::rent_epoch::default()
186pub const INITIAL_RENT_EPOCH: Epoch = 0;
187
188/// An index to the slots of a epoch.
189pub type SlotIndex = u64;
190
191/// The number of slots in a epoch.
192pub type SlotCount = u64;
193
194/// An approximate measure of real-world time.
195///
196/// Expressed as Unix time (i.e. seconds since the Unix epoch).
197pub type UnixTimestamp = i64;
198
199/// A representation of network time.
200///
201/// All members of `Clock` start from 0 upon network boot.
202#[repr(C)]
203#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
204#[cfg_attr(feature = "wincode", derive(wincode::SchemaWrite, wincode::SchemaRead))]
205#[derive(Debug, CloneZeroed, Default, PartialEq, Eq)]
206pub struct Clock {
207    /// The current `Slot`.
208    pub slot: Slot,
209    /// The timestamp of the first `Slot` in this `Epoch`.
210    pub epoch_start_timestamp: UnixTimestamp,
211    /// The current `Epoch`.
212    pub epoch: Epoch,
213    /// The future `Epoch` for which the leader schedule has
214    /// most recently been calculated.
215    pub leader_schedule_epoch: Epoch,
216    /// The approximate real world time of the current slot.
217    ///
218    /// This value was originally computed from genesis creation time and
219    /// network time in slots, incurring a lot of drift. Following activation of
220    /// the [`timestamp_correction` and `timestamp_bounding`][tsc] features it
221    /// is calculated using a [validator timestamp oracle][oracle].
222    ///
223    /// [tsc]: https://docs.solanalabs.com/implemented-proposals/bank-timestamp-correction
224    /// [oracle]: https://docs.solanalabs.com/implemented-proposals/validator-timestamp-oracle
225    pub unix_timestamp: UnixTimestamp,
226}
227
228/// Serialized size of the `Clock` sysvar account.
229pub const SIZE: usize = size_of::<Clock>();
230const _: () = assert!(SIZE == 40);
231
232#[cfg(test)]
233mod tests {
234    use super::*;
235
236    #[test]
237    fn test_size_of() {
238        assert_eq!(
239            wincode::serialized_size(&Clock::default()).unwrap() as usize,
240            SIZE,
241        );
242    }
243
244    #[test]
245    fn test_clone() {
246        let clock = Clock {
247            slot: 1,
248            epoch_start_timestamp: 2,
249            epoch: 3,
250            leader_schedule_epoch: 4,
251            unix_timestamp: 5,
252        };
253        let cloned_clock = clock.clone();
254        assert_eq!(cloned_clock, clock);
255    }
256}