1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
use sbor::Sbor;
/// An index of a specific validator within the current validator set.
/// To be exact: a `ValidatorIndex` equal to `k` references the `k-th` element returned by the
/// iterator of the `IndexMap<ComponentAddress, Validator>` in this epoch's active validator set
/// (which is expected to be sorted by stake, descending).
/// This uniquely identifies the validator, while being shorter than `ComponentAddress` (we do care
/// about the constant factor of the space taken by `LeaderProposalHistory` under prolonged liveness
/// break scenarios).
pub type ValidatorIndex = u8;
/// A type-safe consensus epoch number.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Sbor)]
#[sbor(transparent)]
pub struct Epoch(u64);
impl Epoch {
/// Creates a zero epoch (i.e. pre-genesis).
pub fn zero() -> Self {
Self::of(0)
}
/// Creates an epoch of the given number.
pub fn of(number: u64) -> Self {
Self(number)
}
/// Returns a raw epoch number.
pub fn number(&self) -> u64 {
self.0
}
/// Creates an epoch immediately following this one.
/// Returns `None` if this epoch's number is [`u64::MAX`] (such situation would indicate a bug
/// or a deliberate harm meant by byzantine actors, since regular epoch progression should not
/// reach such numbers within next thousands of years).
pub fn next(&self) -> Option<Self> {
self.0.checked_add(1).map(|x| Self(x))
}
/// Creates an epoch following this one after the given number of epochs.
/// Returns `None` if the resulting number is greater than [`u64::MAX`] (such situation would
/// indicate a bug or a deliberate harm meant by byzantine actors, since regular epoch delays
/// configured by a network should not span thousands of years).
pub fn after(&self, epoch_count: u64) -> Option<Self> {
self.0.checked_add(epoch_count).map(|x| Self(x))
}
/// Creates an epoch immediately preceding this one.
/// Returns `None` if this epoch's number is 0 (such situation would indicate a bug or a
/// deliberate harm, since a legitimate genesis should not reference previous epochs).
pub fn previous(&self) -> Option<Self> {
self.0.checked_sub(1).map(|x| Self(x))
}
}
/// A type-safe consensus round number *within a single epoch*.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Sbor)]
#[sbor(transparent)]
pub struct Round(u64);
impl Round {
/// Creates a zero round (i.e. a state right after progressing to a next epoch).
pub fn zero() -> Self {
Self::of(0)
}
/// Creates a round of the given number.
pub fn of(number: u64) -> Self {
Self(number)
}
/// Returns a raw round number.
pub fn number(&self) -> u64 {
self.0
}
/// Returns a number of rounds between `from` and `to`, or `None` if there was no progress
/// (i.e. their difference was not positive).
pub fn calculate_progress(from: Round, to: Round) -> Option<u64> {
let difference = (to.0 as i128) - (from.0 as i128);
if difference <= 0 {
None
} else {
Some(difference as u64) // if a difference of two u64 is positive, then it fits in u64
}
}
}