cbe_program/clock.rs
1//! Information about the network's clock, ticks, slots, etc.
2//!
3//! Time in Cartallum CBE 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.cartallum.com/implemented-proposals/validator-timestamp-oracle
22
23use cbe_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#[cfg(test)]
48static_assertions::const_assert_eq!(DEFAULT_HASHES_PER_TICK, 12_500);
49pub const DEFAULT_HASHES_PER_TICK: u64 = DEFAULT_HASHES_PER_SECOND / DEFAULT_TICKS_PER_SECOND;
50
51// 1 Dev Epoch = 400 ms * 8192 ~= 55 minutes
52pub const DEFAULT_DEV_SLOTS_PER_EPOCH: u64 = 8192;
53
54#[cfg(test)]
55static_assertions::const_assert_eq!(SECONDS_PER_DAY, 86_400);
56pub const SECONDS_PER_DAY: u64 = 24 * 60 * 60;
57
58#[cfg(test)]
59static_assertions::const_assert_eq!(TICKS_PER_DAY, 13_824_000);
60pub const TICKS_PER_DAY: u64 = DEFAULT_TICKS_PER_SECOND * SECONDS_PER_DAY;
61
62#[cfg(test)]
63static_assertions::const_assert_eq!(DEFAULT_SLOTS_PER_EPOCH, 432_000);
64
65/// The number of slots per epoch after initial network warmup.
66///
67/// 1 Epoch ~= 2 days.
68pub const DEFAULT_SLOTS_PER_EPOCH: u64 = 2 * TICKS_PER_DAY / DEFAULT_TICKS_PER_SLOT;
69
70// leader schedule is governed by this
71pub const NUM_CONSECUTIVE_LEADER_SLOTS: u64 = 4;
72
73#[cfg(test)]
74static_assertions::const_assert_eq!(DEFAULT_MS_PER_SLOT, 400);
75/// The expected duration of a slot (400 milliseconds).
76pub const DEFAULT_MS_PER_SLOT: u64 = 1_000 * DEFAULT_TICKS_PER_SLOT / DEFAULT_TICKS_PER_SECOND;
77pub const DEFAULT_S_PER_SLOT: f64 = DEFAULT_TICKS_PER_SLOT as f64 / DEFAULT_TICKS_PER_SECOND as f64;
78
79/// The time window of recent block hash values over which the bank will track
80/// signatures.
81///
82/// Once the bank discards a block hash, it will reject any transactions that
83/// use that `recent_blockhash` in a transaction. Lowering this value reduces
84/// memory consumption, but requires a client to update its `recent_blockhash`
85/// more frequently. Raising the value lengthens the time a client must wait to
86/// be certain a missing transaction will not be processed by the network.
87pub const MAX_HASH_AGE_IN_SECONDS: usize = 120;
88
89#[cfg(test)]
90static_assertions::const_assert_eq!(MAX_RECENT_BLOCKHASHES, 300);
91// Number of maximum recent blockhashes (one blockhash per non-skipped slot)
92pub const MAX_RECENT_BLOCKHASHES: usize =
93 MAX_HASH_AGE_IN_SECONDS * DEFAULT_TICKS_PER_SECOND as usize / DEFAULT_TICKS_PER_SLOT as usize;
94
95#[cfg(test)]
96static_assertions::const_assert_eq!(MAX_PROCESSING_AGE, 150);
97// The maximum age of a blockhash that will be accepted by the leader
98pub const MAX_PROCESSING_AGE: usize = MAX_RECENT_BLOCKHASHES / 2;
99
100/// This is maximum time consumed in forwarding a transaction from one node to next, before
101/// it can be processed in the target node
102pub const MAX_TRANSACTION_FORWARDING_DELAY_GPU: usize = 2;
103
104/// More delay is expected if CUDA is not enabled (as signature verification takes longer)
105pub const MAX_TRANSACTION_FORWARDING_DELAY: usize = 6;
106
107/// Transaction forwarding, which leader to forward to and how long to hold
108pub const FORWARD_TRANSACTIONS_TO_LEADER_AT_SLOT_OFFSET: u64 = 2;
109pub const HOLD_TRANSACTIONS_SLOT_OFFSET: u64 = 20;
110
111/// The unit of time given to a leader for encoding a block.
112///
113/// It is some some number of _ticks_ long.
114pub type Slot = u64;
115
116/// Uniquely distinguishes every version of a slot.
117///
118/// The `BankId` is unique even if the slot number of two different slots is the
119/// same. This can happen in the case of e.g. duplicate slots.
120pub type BankId = u64;
121
122/// The unit of time a given leader schedule is honored.
123///
124/// It lasts for some number of [`Slot`]s.
125pub type Epoch = u64;
126
127pub const GENESIS_EPOCH: Epoch = 0;
128// must be sync with Account::rent_epoch::default()
129pub const INITIAL_RENT_EPOCH: Epoch = 0;
130
131/// An index to the slots of a epoch.
132pub type SlotIndex = u64;
133
134/// The number of slots in a epoch.
135pub type SlotCount = u64;
136
137/// An approximate measure of real-world time.
138///
139/// Expressed as Unix time (i.e. seconds since the Unix epoch).
140pub type UnixTimestamp = i64;
141
142/// A representation of network time.
143///
144/// All members of `Clock` start from 0 upon network boot.
145#[repr(C)]
146#[derive(Serialize, Deserialize, Debug, CloneZeroed, Default, PartialEq, Eq)]
147pub struct Clock {
148 /// The current `Slot`.
149 pub slot: Slot,
150 /// The timestamp of the first `Slot` in this `Epoch`.
151 pub epoch_start_timestamp: UnixTimestamp,
152 /// The current `Epoch`.
153 pub epoch: Epoch,
154 /// The future `Epoch` for which the leader schedule has
155 /// most recently been calculated.
156 pub leader_schedule_epoch: Epoch,
157 /// The approximate real world time of the current slot.
158 ///
159 /// This value was originally computed from genesis creation time and
160 /// network time in slots, incurring a lot of drift. Following activation of
161 /// the [`timestamp_correction` and `timestamp_bounding`][tsc] features it
162 /// is calculated using a [validator timestamp oracle][oracle].
163 ///
164 /// [tsc]: https://docs.cartallum.com/implemented-proposals/bank-timestamp-correction
165 /// [oracle]: https://docs.cartallum.com/implemented-proposals/validator-timestamp-oracle
166 pub unix_timestamp: UnixTimestamp,
167}
168
169#[cfg(test)]
170mod tests {
171 use super::*;
172
173 #[test]
174 fn test_clone() {
175 let clock = Clock {
176 slot: 1,
177 epoch_start_timestamp: 2,
178 epoch: 3,
179 leader_schedule_epoch: 4,
180 unix_timestamp: 5,
181 };
182 let cloned_clock = clock.clone();
183 assert_eq!(cloned_clock, clock);
184 }
185}