Add first impl of Slot and Epoch newtypes
Not tested yet.
This commit is contained in:
parent
af35bccd7c
commit
dbe9112848
@ -22,6 +22,7 @@ pub mod proposer_slashing;
|
|||||||
pub mod shard_committee;
|
pub mod shard_committee;
|
||||||
pub mod shard_reassignment_record;
|
pub mod shard_reassignment_record;
|
||||||
pub mod slashable_vote_data;
|
pub mod slashable_vote_data;
|
||||||
|
pub mod slot_epoch;
|
||||||
pub mod spec;
|
pub mod spec;
|
||||||
pub mod special_record;
|
pub mod special_record;
|
||||||
pub mod validator;
|
pub mod validator;
|
||||||
|
|||||||
208
eth2/types/src/slot_epoch.rs
Normal file
208
eth2/types/src/slot_epoch.rs
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
/// The `Slot` and `Epoch` types are defined as newtypes over u64 to enforce type-safety between
|
||||||
|
/// the two types.
|
||||||
|
///
|
||||||
|
/// `Slot` and `Epoch` have implementations which permit conversion, comparison and math operations
|
||||||
|
/// between each and `u64`, however specifically not between each other.
|
||||||
|
///
|
||||||
|
/// All math operations on `Slot` and `Epoch` are saturating, they never wrap.
|
||||||
|
///
|
||||||
|
/// It would be easy to define `PartialOrd` and other traits generically across all types which
|
||||||
|
/// implement `Into<u64>`, however this would allow operations between `Slots` and `Epochs` which
|
||||||
|
/// may lead to programming errors which are not detected by the compiler.
|
||||||
|
use crate::test_utils::TestRandom;
|
||||||
|
use crate::ChainSpec;
|
||||||
|
use rand::RngCore;
|
||||||
|
use serde_derive::Serialize;
|
||||||
|
use ssz::{hash, Decodable, DecodeError, Encodable, SszStream, TreeHash};
|
||||||
|
use std::cmp::{Ord, Ordering};
|
||||||
|
use std::fmt;
|
||||||
|
use std::ops::{Add, AddAssign, Rem, Sub, SubAssign};
|
||||||
|
|
||||||
|
macro_rules! impl_from_into_u64 {
|
||||||
|
($main: ident) => {
|
||||||
|
impl From<u64> for $main {
|
||||||
|
fn from(n: u64) -> $main {
|
||||||
|
$main(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<u64> for $main {
|
||||||
|
fn into(self) -> u64 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $main {
|
||||||
|
pub fn as_u64(&self) -> u64 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_from_into_usize {
|
||||||
|
($main: ident) => {
|
||||||
|
impl From<usize> for $main {
|
||||||
|
fn from(n: usize) -> $main {
|
||||||
|
$main(n as u64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<usize> for $main {
|
||||||
|
fn into(self) -> usize {
|
||||||
|
self.0 as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $main {
|
||||||
|
pub fn as_usize(&self) -> usize {
|
||||||
|
self.0 as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_math_between {
|
||||||
|
($main: ident, $other: ident) => {
|
||||||
|
impl PartialOrd<$other> for $main {
|
||||||
|
/// Utilizes `partial_cmp` on the underlying `u64`.
|
||||||
|
fn partial_cmp(&self, other: &$other) -> Option<Ordering> {
|
||||||
|
Some(self.0.cmp(&(*other).into()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq<$other> for $main {
|
||||||
|
fn eq(&self, other: &$other) -> bool {
|
||||||
|
let other: u64 = (*other).into();
|
||||||
|
self.0 == other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add<$other> for $main {
|
||||||
|
type Output = $main;
|
||||||
|
|
||||||
|
fn add(self, other: $other) -> $main {
|
||||||
|
$main::from(self.0.saturating_add(other.into()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddAssign<$other> for $main {
|
||||||
|
fn add_assign(&mut self, other: $other) {
|
||||||
|
self.0.saturating_add(other.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub<$other> for $main {
|
||||||
|
type Output = $main;
|
||||||
|
|
||||||
|
fn sub(self, other: $other) -> $main {
|
||||||
|
$main::from(self.0.saturating_sub(other.into()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SubAssign<$other> for $main {
|
||||||
|
fn sub_assign(&mut self, other: $other) {
|
||||||
|
self.0.saturating_sub(other.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Rem<$other> for $main {
|
||||||
|
type Output = $main;
|
||||||
|
|
||||||
|
fn rem(self, modulus: $other) -> $main {
|
||||||
|
let modulus: u64 = modulus.into();
|
||||||
|
$main::from(self.0 % modulus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_display {
|
||||||
|
($type: ident) => {
|
||||||
|
impl fmt::Display for $type {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_ssz {
|
||||||
|
($type: ident) => {
|
||||||
|
impl Encodable for $type {
|
||||||
|
fn ssz_append(&self, s: &mut SszStream) {
|
||||||
|
s.append(&self.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable for $type {
|
||||||
|
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
|
||||||
|
let (value, i) = <_>::ssz_decode(bytes, i)?;
|
||||||
|
|
||||||
|
Ok(($type(value), i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TreeHash for $type {
|
||||||
|
fn hash_tree_root(&self) -> Vec<u8> {
|
||||||
|
let mut result: Vec<u8> = vec![];
|
||||||
|
result.append(&mut self.0.hash_tree_root());
|
||||||
|
hash(&result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: RngCore> TestRandom<T> for $type {
|
||||||
|
fn random_for_test(rng: &mut T) -> Self {
|
||||||
|
$type::from(u64::random_for_test(rng))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, Debug, Clone, Copy, Default, Serialize, Hash)]
|
||||||
|
pub struct Slot(u64);
|
||||||
|
|
||||||
|
#[derive(Eq, Debug, Clone, Copy, Default, Serialize, Hash)]
|
||||||
|
pub struct Epoch(u64);
|
||||||
|
|
||||||
|
impl_from_into_u64!(Slot);
|
||||||
|
impl_from_into_usize!(Slot);
|
||||||
|
impl_math_between!(Slot, Slot);
|
||||||
|
impl_math_between!(Slot, u64);
|
||||||
|
impl_display!(Slot);
|
||||||
|
impl_ssz!(Slot);
|
||||||
|
|
||||||
|
impl_from_into_u64!(Epoch);
|
||||||
|
impl_from_into_usize!(Epoch);
|
||||||
|
impl_math_between!(Epoch, Epoch);
|
||||||
|
impl_math_between!(Epoch, u64);
|
||||||
|
impl_display!(Epoch);
|
||||||
|
impl_ssz!(Epoch);
|
||||||
|
|
||||||
|
impl Slot {
|
||||||
|
pub fn epoch(&self, spec: &ChainSpec) -> Epoch {
|
||||||
|
Epoch::from(self.0 / spec.epoch_length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Epoch {
|
||||||
|
pub fn start_slot(&self, spec: &ChainSpec) -> Slot {
|
||||||
|
Slot::from(self.0.saturating_mul(spec.epoch_length))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn end_slot(&self, spec: &ChainSpec) -> Slot {
|
||||||
|
Slot::from(
|
||||||
|
self.0
|
||||||
|
.saturating_add(1)
|
||||||
|
.saturating_mul(spec.epoch_length)
|
||||||
|
.saturating_sub(1),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn slots(&self, spec: &ChainSpec) -> Vec<Slot> {
|
||||||
|
(self.start_slot(spec).as_u64()..self.end_slot(spec).as_u64())
|
||||||
|
.into_iter()
|
||||||
|
.map(|i| Slot::from(i))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user