Convert beacon_state
to Slot/Epoch newtypes
This commit is contained in:
parent
2aa7d80a5f
commit
bd71304d73
@ -1,7 +1,7 @@
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{
|
||||
validator::StatusFlags, validator_registry::get_active_validator_indices, AggregatePublicKey,
|
||||
Attestation, AttestationData, BeaconBlock, Bitfield, ChainSpec, Crosslink, Eth1Data,
|
||||
Attestation, AttestationData, BeaconBlock, Bitfield, ChainSpec, Crosslink, Epoch, Eth1Data,
|
||||
Eth1DataVote, Exit, Fork, Hash256, PendingAttestation, PublicKey, Signature, Slot, Validator,
|
||||
};
|
||||
use bls::bls_verify_aggregate;
|
||||
@ -28,7 +28,7 @@ const DOMAIN_ATTESTATION: u64 = 1;
|
||||
pub enum Error {
|
||||
InsufficientValidators,
|
||||
BadBlockSignature,
|
||||
InvalidEpoch(u64, Range<u64>),
|
||||
InvalidEpoch(Slot, Range<Epoch>),
|
||||
CommitteesError(CommitteesError),
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ pub enum WinningRootError {
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum CommitteesError {
|
||||
InvalidEpoch(u64, Range<u64>),
|
||||
InvalidEpoch,
|
||||
InsufficientNumberOfValidators,
|
||||
}
|
||||
|
||||
@ -198,20 +198,20 @@ impl BeaconState {
|
||||
Hash256::from(&self.hash_tree_root()[..])
|
||||
}
|
||||
|
||||
pub fn current_epoch(&self, spec: &ChainSpec) -> u64 {
|
||||
self.slot / spec.epoch_length
|
||||
pub fn current_epoch(&self, spec: &ChainSpec) -> Epoch {
|
||||
self.slot.epoch(spec.epoch_length)
|
||||
}
|
||||
|
||||
pub fn previous_epoch(&self, spec: &ChainSpec) -> u64 {
|
||||
self.current_epoch(spec).saturating_sub(1)
|
||||
pub fn previous_epoch(&self, spec: &ChainSpec) -> Epoch {
|
||||
self.current_epoch(spec).saturating_sub(1_u64)
|
||||
}
|
||||
|
||||
pub fn current_epoch_start_slot(&self, spec: &ChainSpec) -> u64 {
|
||||
self.current_epoch(spec) * spec.epoch_length
|
||||
pub fn current_epoch_start_slot(&self, spec: &ChainSpec) -> Slot {
|
||||
self.current_epoch(spec).start_slot(spec.epoch_length)
|
||||
}
|
||||
|
||||
pub fn previous_epoch_start_slot(&self, spec: &ChainSpec) -> u64 {
|
||||
self.previous_epoch(spec) * spec.epoch_length
|
||||
pub fn previous_epoch_start_slot(&self, spec: &ChainSpec) -> Slot {
|
||||
self.previous_epoch(spec).start_slot(spec.epoch_length)
|
||||
}
|
||||
|
||||
/// Returns the number of committees per slot.
|
||||
@ -231,23 +231,6 @@ impl BeaconState {
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the start slot and end slot of the current epoch containing `self.slot`.
|
||||
pub fn get_current_epoch_boundaries(&self, epoch_length: u64) -> Range<u64> {
|
||||
let slot_in_epoch = self.slot % epoch_length;
|
||||
let start = self.slot - slot_in_epoch;
|
||||
let end = self.slot + (epoch_length - slot_in_epoch);
|
||||
start..end
|
||||
}
|
||||
|
||||
/// Returns the start slot and end slot of the current epoch containing `self.slot`.
|
||||
pub fn get_previous_epoch_boundaries(&self, spec: &ChainSpec) -> Range<u64> {
|
||||
let current_epoch = self.slot / spec.epoch_length;
|
||||
let previous_epoch = current_epoch.saturating_sub(1);
|
||||
let start = previous_epoch * spec.epoch_length;
|
||||
let end = start + spec.epoch_length;
|
||||
start..end
|
||||
}
|
||||
|
||||
fn get_previous_epoch_committee_count_per_slot(&self, spec: &ChainSpec) -> u64 {
|
||||
let previous_active_validators = get_active_validator_indices(
|
||||
&self.validator_registry,
|
||||
@ -266,24 +249,24 @@ impl BeaconState {
|
||||
|
||||
pub fn get_crosslink_committees_at_slot(
|
||||
&self,
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Vec<(Vec<usize>, u64)>, CommitteesError> {
|
||||
let epoch = slot / spec.epoch_length;
|
||||
let current_epoch = self.slot / spec.epoch_length;
|
||||
let previous_epoch = if current_epoch == spec.genesis_slot {
|
||||
let epoch = slot.epoch(spec.epoch_length);
|
||||
let current_epoch = self.current_epoch(spec);
|
||||
let previous_epoch = if current_epoch == spec.genesis_slot.epoch(spec.epoch_length) {
|
||||
current_epoch
|
||||
} else {
|
||||
current_epoch.saturating_sub(1)
|
||||
current_epoch.saturating_sub(1_u64)
|
||||
};
|
||||
let next_epoch = current_epoch + 1;
|
||||
|
||||
ensure!(
|
||||
(previous_epoch <= epoch) & (epoch < next_epoch),
|
||||
CommitteesError::InvalidEpoch(slot, previous_epoch..current_epoch)
|
||||
CommitteesError::InvalidEpoch
|
||||
);
|
||||
|
||||
let offset = slot % spec.epoch_length;
|
||||
let offset = slot.as_u64() % spec.epoch_length;
|
||||
|
||||
let (committees_per_slot, shuffling, slot_start_shard) = if epoch < current_epoch {
|
||||
let committees_per_slot = self.get_previous_epoch_committee_count_per_slot(spec);
|
||||
@ -332,11 +315,11 @@ impl BeaconState {
|
||||
let block_proposer = self.get_beacon_proposer_index(self.slot, spec)?;
|
||||
|
||||
self.validator_registry[block_proposer].proposer_slots += 1;
|
||||
self.latest_randao_mixes[(self.slot % spec.latest_randao_mixes_length) as usize] =
|
||||
self.latest_randao_mixes[((self.slot - 1) % spec.latest_randao_mixes_length) as usize];
|
||||
self.latest_randao_mixes[(self.slot % spec.latest_randao_mixes_length).as_usize()] = self
|
||||
.latest_randao_mixes[((self.slot - 1) % spec.latest_randao_mixes_length).as_usize()];
|
||||
|
||||
// Block roots.
|
||||
self.latest_block_roots[((self.slot - 1) % spec.latest_block_roots_length) as usize] =
|
||||
self.latest_block_roots[((self.slot - 1) % spec.latest_block_roots_length).as_usize()] =
|
||||
previous_block_root;
|
||||
|
||||
if self.slot % spec.latest_block_roots_length == 0 {
|
||||
@ -350,9 +333,9 @@ impl BeaconState {
|
||||
&self,
|
||||
validator_index: usize,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Option<(u64, u64, u64)>, CommitteesError> {
|
||||
) -> Result<Option<(Slot, u64, u64)>, CommitteesError> {
|
||||
let mut result = None;
|
||||
for slot in self.get_current_epoch_boundaries(spec.epoch_length) {
|
||||
for slot in self.current_epoch(spec).slot_iter(spec.epoch_length) {
|
||||
for (committee, shard) in self.get_crosslink_committees_at_slot(slot, spec)? {
|
||||
if let Some(committee_index) = committee.iter().position(|&i| i == validator_index)
|
||||
{
|
||||
@ -426,13 +409,14 @@ impl BeaconState {
|
||||
// TODO: check this is correct.
|
||||
let new_mix = {
|
||||
let mut mix = self.latest_randao_mixes
|
||||
[(self.slot % spec.latest_randao_mixes_length) as usize]
|
||||
[(self.slot % spec.latest_randao_mixes_length).as_usize()]
|
||||
.to_vec();
|
||||
mix.append(&mut ssz_encode(&block.randao_reveal));
|
||||
Hash256::from(&hash(&mix)[..])
|
||||
};
|
||||
|
||||
self.latest_randao_mixes[(self.slot % spec.latest_randao_mixes_length) as usize] = new_mix;
|
||||
self.latest_randao_mixes[(self.slot % spec.latest_randao_mixes_length).as_usize()] =
|
||||
new_mix;
|
||||
|
||||
/*
|
||||
* Eth1 data
|
||||
@ -593,7 +577,7 @@ impl BeaconState {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_shuffling(&self, seed: Hash256, slot: u64, spec: &ChainSpec) -> Vec<Vec<usize>> {
|
||||
pub fn get_shuffling(&self, seed: Hash256, slot: Slot, spec: &ChainSpec) -> Vec<Vec<usize>> {
|
||||
let slot = slot - (slot % spec.epoch_length);
|
||||
|
||||
let active_validator_indices = get_active_validator_indices(&self.validator_registry, slot);
|
||||
@ -602,7 +586,7 @@ impl BeaconState {
|
||||
self.get_committee_count_per_slot(active_validator_indices.len(), spec);
|
||||
|
||||
// TODO: check that Hash256 matches 'int_to_bytes32'.
|
||||
let seed = seed ^ Hash256::from(slot);
|
||||
let seed = seed ^ Hash256::from(slot.as_u64());
|
||||
let shuffled_active_validator_indices =
|
||||
shuffle(&seed, active_validator_indices).expect("Max validator count exceed!");
|
||||
|
||||
@ -616,7 +600,7 @@ impl BeaconState {
|
||||
/// If the state does not contain an index for a beacon proposer at the requested `slot`, then `None` is returned.
|
||||
pub fn get_beacon_proposer_index(
|
||||
&self,
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<usize, CommitteesError> {
|
||||
let committees = self.get_crosslink_committees_at_slot(slot, spec)?;
|
||||
@ -624,7 +608,7 @@ impl BeaconState {
|
||||
.first()
|
||||
.ok_or(CommitteesError::InsufficientNumberOfValidators)
|
||||
.and_then(|(first_committee, _)| {
|
||||
let index = (slot as usize)
|
||||
let index = (slot.as_usize())
|
||||
.checked_rem(first_committee.len())
|
||||
.ok_or(CommitteesError::InsufficientNumberOfValidators)?;
|
||||
// NOTE: next index will not panic as we have already returned if this is the case
|
||||
@ -653,7 +637,10 @@ impl BeaconState {
|
||||
let current_epoch_attestations: Vec<&PendingAttestation> = self
|
||||
.latest_attestations
|
||||
.par_iter()
|
||||
.filter(|a| a.data.slot / spec.epoch_length == self.current_epoch(spec))
|
||||
.filter(|a| {
|
||||
(a.data.slot / spec.epoch_length).epoch(spec.epoch_length)
|
||||
== self.current_epoch(spec)
|
||||
})
|
||||
.collect();
|
||||
|
||||
debug!(
|
||||
@ -708,7 +695,8 @@ impl BeaconState {
|
||||
.par_iter()
|
||||
.filter(|a| {
|
||||
//TODO: ensure these saturating subs are correct.
|
||||
a.data.slot / spec.epoch_length == self.previous_epoch(spec)
|
||||
(a.data.slot / spec.epoch_length).epoch(spec.epoch_length)
|
||||
== self.previous_epoch(spec)
|
||||
})
|
||||
.collect();
|
||||
|
||||
@ -864,7 +852,7 @@ impl BeaconState {
|
||||
HashMap::new();
|
||||
|
||||
// for slot in self.slot.saturating_sub(2 * spec.epoch_length)..self.slot {
|
||||
for slot in self.get_previous_epoch_boundaries(spec) {
|
||||
for slot in self.previous_epoch(spec).slot_iter(spec.epoch_length) {
|
||||
let crosslink_committees_at_slot = self.get_crosslink_committees_at_slot(slot, spec)?;
|
||||
|
||||
for (crosslink_committee, shard) in crosslink_committees_at_slot {
|
||||
@ -909,7 +897,7 @@ impl BeaconState {
|
||||
* Justification and finalization
|
||||
*/
|
||||
let epochs_since_finality =
|
||||
self.slot.saturating_sub(self.finalized_slot) / spec.epoch_length;
|
||||
(self.slot.saturating_sub(self.finalized_slot) / spec.epoch_length).as_u64();
|
||||
|
||||
// TODO: fix this extra map
|
||||
let previous_epoch_justified_attester_indices_hashset: HashSet<usize> =
|
||||
@ -1028,7 +1016,7 @@ impl BeaconState {
|
||||
/*
|
||||
* Crosslinks
|
||||
*/
|
||||
for slot in self.get_previous_epoch_boundaries(spec) {
|
||||
for slot in self.previous_epoch(spec).slot_iter(spec.epoch_length) {
|
||||
let crosslink_committees_at_slot = self.get_crosslink_committees_at_slot(slot, spec)?;
|
||||
|
||||
for (_crosslink_committee, shard) in crosslink_committees_at_slot {
|
||||
@ -1097,8 +1085,7 @@ impl BeaconState {
|
||||
+ self.get_current_epoch_committee_count_per_slot(spec) as u64 * spec.epoch_length)
|
||||
% spec.shard_count;
|
||||
self.current_epoch_seed = self.get_randao_mix(
|
||||
self.current_epoch_calculation_slot
|
||||
.saturating_sub(spec.seed_lookahead),
|
||||
self.current_epoch_calculation_slot - spec.seed_lookahead,
|
||||
spec,
|
||||
);
|
||||
} else {
|
||||
@ -1107,8 +1094,7 @@ impl BeaconState {
|
||||
if epochs_since_last_registry_change.is_power_of_two() {
|
||||
self.current_epoch_calculation_slot = self.slot;
|
||||
self.current_epoch_seed = self.get_randao_mix(
|
||||
self.current_epoch_calculation_slot
|
||||
.saturating_sub(spec.seed_lookahead),
|
||||
self.current_epoch_calculation_slot - spec.seed_lookahead,
|
||||
spec,
|
||||
);
|
||||
}
|
||||
@ -1117,13 +1103,16 @@ impl BeaconState {
|
||||
self.process_penalties_and_exits(spec);
|
||||
|
||||
let e = self.slot / spec.epoch_length;
|
||||
self.latest_penalized_balances[((e + 1) % spec.latest_penalized_exit_length) as usize] =
|
||||
self.latest_penalized_balances[(e % spec.latest_penalized_exit_length) as usize];
|
||||
self.latest_penalized_balances[((e + 1) % spec.latest_penalized_exit_length).as_usize()] =
|
||||
self.latest_penalized_balances[(e % spec.latest_penalized_exit_length).as_usize()];
|
||||
|
||||
self.latest_attestations = self
|
||||
.latest_attestations
|
||||
.iter()
|
||||
.filter(|a| a.data.slot / spec.epoch_length >= self.current_epoch(spec))
|
||||
.filter(|a| {
|
||||
(a.data.slot / spec.epoch_length).epoch(spec.epoch_length)
|
||||
>= self.current_epoch(spec)
|
||||
})
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
@ -1146,8 +1135,8 @@ impl BeaconState {
|
||||
{
|
||||
let e = (self.slot / spec.epoch_length) % spec.latest_penalized_exit_length;
|
||||
let total_at_start = self.latest_penalized_balances
|
||||
[((e + 1) % spec.latest_penalized_exit_length) as usize];
|
||||
let total_at_end = self.latest_penalized_balances[e as usize];
|
||||
[((e + 1) % spec.latest_penalized_exit_length).as_usize()];
|
||||
let total_at_end = self.latest_penalized_balances[e.as_usize()];
|
||||
let total_penalities = total_at_end.saturating_sub(total_at_start);
|
||||
let penalty = self.get_effective_balance(index, spec)
|
||||
* std::cmp::min(total_penalities * 3, total_balance)
|
||||
@ -1187,10 +1176,10 @@ impl BeaconState {
|
||||
self.validator_registry[index].status_flags = Some(StatusFlags::Withdrawable);
|
||||
}
|
||||
|
||||
fn get_randao_mix(&mut self, slot: u64, spec: &ChainSpec) -> Hash256 {
|
||||
fn get_randao_mix(&mut self, slot: Slot, spec: &ChainSpec) -> Hash256 {
|
||||
assert!(self.slot < slot + spec.latest_randao_mixes_length);
|
||||
assert!(slot <= self.slot);
|
||||
self.latest_randao_mixes[(slot & spec.latest_randao_mixes_length) as usize]
|
||||
self.latest_randao_mixes[(slot % spec.latest_randao_mixes_length).as_usize()]
|
||||
}
|
||||
|
||||
fn update_validator_registry(&mut self, spec: &ChainSpec) {
|
||||
@ -1260,7 +1249,7 @@ impl BeaconState {
|
||||
}
|
||||
}
|
||||
|
||||
fn entry_exit_effect_slot(&self, slot: u64, spec: &ChainSpec) -> u64 {
|
||||
fn entry_exit_effect_slot(&self, slot: Slot, spec: &ChainSpec) -> Slot {
|
||||
(slot - slot % spec.epoch_length) + spec.epoch_length + spec.entry_exit_delay
|
||||
}
|
||||
|
||||
@ -1288,9 +1277,7 @@ impl BeaconState {
|
||||
) -> Result<u64, InclusionError> {
|
||||
let attestation =
|
||||
self.earliest_included_attestation(attestations, validator_index, spec)?;
|
||||
Ok(attestation
|
||||
.slot_included
|
||||
.saturating_sub(attestation.data.slot))
|
||||
Ok((attestation.slot_included - attestation.data.slot).as_u64())
|
||||
}
|
||||
|
||||
fn inclusion_slot(
|
||||
@ -1298,7 +1285,7 @@ impl BeaconState {
|
||||
attestations: &[&PendingAttestation],
|
||||
validator_index: usize,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<u64, InclusionError> {
|
||||
) -> Result<Slot, InclusionError> {
|
||||
let attestation =
|
||||
self.earliest_included_attestation(attestations, validator_index, spec)?;
|
||||
Ok(attestation.slot_included)
|
||||
@ -1350,10 +1337,10 @@ impl BeaconState {
|
||||
std::cmp::min(self.validator_balances[validator_index], spec.max_deposit)
|
||||
}
|
||||
|
||||
pub fn get_block_root(&self, slot: u64, spec: &ChainSpec) -> Option<&Hash256> {
|
||||
pub fn get_block_root(&self, slot: Slot, spec: &ChainSpec) -> Option<&Hash256> {
|
||||
if self.slot <= slot + spec.latest_block_roots_length && slot <= self.slot {
|
||||
self.latest_block_roots
|
||||
.get((slot % spec.latest_block_roots_length) as usize)
|
||||
.get((slot % spec.latest_block_roots_length).as_usize())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -1589,7 +1576,7 @@ fn penalize_validator(_state: &BeaconState, _proposer_index: usize) {
|
||||
// TODO: stubbed out.
|
||||
}
|
||||
|
||||
fn get_domain(_fork: &Fork, _slot: u64, _domain_type: u64) -> u64 {
|
||||
fn get_domain(_fork: &Fork, _slot: Slot, _domain_type: u64) -> u64 {
|
||||
// TODO: stubbed out.
|
||||
0
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
use super::state_reader::BeaconStateReader;
|
||||
use crate::{BeaconBlock, Hash256};
|
||||
use crate::{BeaconBlock, Hash256, Slot};
|
||||
use std::fmt::Debug;
|
||||
|
||||
/// The `BeaconBlockReader` provides interfaces for reading a subset of fields of a `BeaconBlock`.
|
||||
@ -11,7 +10,7 @@ use std::fmt::Debug;
|
||||
/// Note: presently, direct SSZ reading has not been implemented so this trait is being used for
|
||||
/// "future proofing".
|
||||
pub trait BeaconBlockReader: Debug + PartialEq {
|
||||
fn slot(&self) -> u64;
|
||||
fn slot(&self) -> Slot;
|
||||
fn parent_root(&self) -> Hash256;
|
||||
fn state_root(&self) -> Hash256;
|
||||
fn canonical_root(&self) -> Hash256;
|
||||
@ -19,7 +18,7 @@ pub trait BeaconBlockReader: Debug + PartialEq {
|
||||
}
|
||||
|
||||
impl BeaconBlockReader for BeaconBlock {
|
||||
fn slot(&self) -> u64 {
|
||||
fn slot(&self) -> Slot {
|
||||
self.slot
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::{BeaconState, Hash256};
|
||||
use crate::{BeaconState, Hash256, Slot};
|
||||
use std::fmt::Debug;
|
||||
|
||||
/// The `BeaconStateReader` provides interfaces for reading a subset of fields of a `BeaconState`.
|
||||
@ -10,13 +10,13 @@ use std::fmt::Debug;
|
||||
/// Note: presently, direct SSZ reading has not been implemented so this trait is being used for
|
||||
/// "future proofing".
|
||||
pub trait BeaconStateReader: Debug + PartialEq {
|
||||
fn slot(&self) -> u64;
|
||||
fn slot(&self) -> Slot;
|
||||
fn canonical_root(&self) -> Hash256;
|
||||
fn into_beacon_state(self) -> Option<BeaconState>;
|
||||
}
|
||||
|
||||
impl BeaconStateReader for BeaconState {
|
||||
fn slot(&self) -> u64 {
|
||||
fn slot(&self) -> Slot {
|
||||
self.slot
|
||||
}
|
||||
|
||||
|
@ -10,13 +10,13 @@
|
||||
/// 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};
|
||||
use std::iter::Iterator;
|
||||
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, Sub, SubAssign};
|
||||
|
||||
macro_rules! impl_from_into_u64 {
|
||||
($main: ident) => {
|
||||
@ -88,7 +88,7 @@ macro_rules! impl_math_between {
|
||||
|
||||
impl AddAssign<$other> for $main {
|
||||
fn add_assign(&mut self, other: $other) {
|
||||
self.0.saturating_add(other.into());
|
||||
self.0 = self.0.saturating_add(other.into());
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,7 +102,45 @@ macro_rules! impl_math_between {
|
||||
|
||||
impl SubAssign<$other> for $main {
|
||||
fn sub_assign(&mut self, other: $other) {
|
||||
self.0.saturating_sub(other.into());
|
||||
self.0 = self.0.saturating_sub(other.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<$other> for $main {
|
||||
type Output = $main;
|
||||
|
||||
fn mul(self, rhs: $other) -> $main {
|
||||
let rhs: u64 = rhs.into();
|
||||
$main::from(self.0.saturating_mul(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign<$other> for $main {
|
||||
fn mul_assign(&mut self, rhs: $other) {
|
||||
let rhs: u64 = rhs.into();
|
||||
self.0 = self.0.saturating_mul(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<$other> for $main {
|
||||
type Output = $main;
|
||||
|
||||
fn div(self, rhs: $other) -> $main {
|
||||
let rhs: u64 = rhs.into();
|
||||
if rhs == 0 {
|
||||
panic!("Cannot divide by zero-valued Slot/Epoch")
|
||||
}
|
||||
$main::from(self.0 / rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl DivAssign<$other> for $main {
|
||||
fn div_assign(&mut self, rhs: $other) {
|
||||
let rhs: u64 = rhs.into();
|
||||
if rhs == 0 {
|
||||
panic!("Cannot divide by zero-valued Slot/Epoch")
|
||||
}
|
||||
self.0 = self.0 / rhs
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,6 +155,27 @@ macro_rules! impl_math_between {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_math {
|
||||
($type: ident) => {
|
||||
impl $type {
|
||||
pub fn saturating_sub<T: Into<$type>>(&self, other: T) -> $type {
|
||||
*self - other.into()
|
||||
}
|
||||
|
||||
pub fn is_power_of_two(&self) -> bool {
|
||||
self.0.is_power_of_two()
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for $type {
|
||||
fn cmp(&self, other: &$type) -> Ordering {
|
||||
let other: u64 = (*other).into();
|
||||
self.0.cmp(&other)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_display {
|
||||
($type: ident) => {
|
||||
impl fmt::Display for $type {
|
||||
@ -169,6 +228,7 @@ impl_from_into_u64!(Slot);
|
||||
impl_from_into_usize!(Slot);
|
||||
impl_math_between!(Slot, Slot);
|
||||
impl_math_between!(Slot, u64);
|
||||
impl_math!(Slot);
|
||||
impl_display!(Slot);
|
||||
impl_ssz!(Slot);
|
||||
|
||||
@ -176,33 +236,59 @@ impl_from_into_u64!(Epoch);
|
||||
impl_from_into_usize!(Epoch);
|
||||
impl_math_between!(Epoch, Epoch);
|
||||
impl_math_between!(Epoch, u64);
|
||||
impl_math!(Epoch);
|
||||
impl_display!(Epoch);
|
||||
impl_ssz!(Epoch);
|
||||
|
||||
impl Slot {
|
||||
pub fn epoch(&self, spec: &ChainSpec) -> Epoch {
|
||||
Epoch::from(self.0 / spec.epoch_length)
|
||||
pub fn epoch(&self, epoch_length: u64) -> Epoch {
|
||||
Epoch::from(self.0 / epoch_length)
|
||||
}
|
||||
|
||||
pub fn max_value() -> Slot {
|
||||
Slot(u64::max_value())
|
||||
}
|
||||
}
|
||||
|
||||
impl Epoch {
|
||||
pub fn start_slot(&self, spec: &ChainSpec) -> Slot {
|
||||
Slot::from(self.0.saturating_mul(spec.epoch_length))
|
||||
pub fn start_slot(&self, epoch_length: u64) -> Slot {
|
||||
Slot::from(self.0.saturating_mul(epoch_length))
|
||||
}
|
||||
|
||||
pub fn end_slot(&self, spec: &ChainSpec) -> Slot {
|
||||
pub fn end_slot(&self, epoch_length: u64) -> Slot {
|
||||
Slot::from(
|
||||
self.0
|
||||
.saturating_add(1)
|
||||
.saturating_mul(spec.epoch_length)
|
||||
.saturating_mul(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()
|
||||
pub fn slot_iter(&self, epoch_length: u64) -> SlotIter {
|
||||
SlotIter {
|
||||
current: self.start_slot(epoch_length),
|
||||
epoch: self,
|
||||
epoch_length,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SlotIter<'a> {
|
||||
current: Slot,
|
||||
epoch: &'a Epoch,
|
||||
epoch_length: u64,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for SlotIter<'a> {
|
||||
type Item = Slot;
|
||||
|
||||
fn next(&mut self) -> Option<Slot> {
|
||||
if self.current == self.epoch.end_slot(self.epoch_length) {
|
||||
None
|
||||
} else {
|
||||
let previous = self.current;
|
||||
self.current += 1;
|
||||
Some(previous)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::ChainSpec;
|
||||
use bls::{Keypair, PublicKey, SecretKey, Signature};
|
||||
|
||||
use crate::{Address, Eth1Data, Hash256, Validator};
|
||||
use crate::{Address, Eth1Data, Hash256, Slot, Validator};
|
||||
|
||||
/// The size of a validators deposit in GWei.
|
||||
pub const DEPOSIT_GWEI: u64 = 32_000_000_000;
|
||||
@ -37,9 +37,9 @@ impl ChainSpec {
|
||||
* Initial Values
|
||||
*/
|
||||
genesis_fork_version: 0,
|
||||
genesis_slot: 0,
|
||||
genesis_slot: Slot::from(0_u64),
|
||||
genesis_start_shard: 0,
|
||||
far_future_slot: u64::max_value(),
|
||||
far_future_slot: Slot::from(u64::max_value()),
|
||||
zero_hash: Hash256::zero(),
|
||||
empty_signature: Signature::empty_signature(),
|
||||
bls_withdrawal_prefix_byte: 0x00,
|
||||
@ -109,15 +109,15 @@ fn initial_validators_for_testing() -> Vec<Validator> {
|
||||
let validator = Validator {
|
||||
pubkey: keypair.pk.clone(),
|
||||
withdrawal_credentials: Hash256::zero(),
|
||||
proposer_slots: 0,
|
||||
activation_slot: u64::max_value(),
|
||||
exit_slot: u64::max_value(),
|
||||
withdrawal_slot: u64::max_value(),
|
||||
penalized_slot: u64::max_value(),
|
||||
proposer_slots: Slot::from(0_u64),
|
||||
activation_slot: Slot::max_value(),
|
||||
exit_slot: Slot::max_value(),
|
||||
withdrawal_slot: Slot::max_value(),
|
||||
penalized_slot: Slot::max_value(),
|
||||
exit_count: 0,
|
||||
status_flags: None,
|
||||
latest_custody_reseed_slot: 0,
|
||||
penultimate_custody_reseed_slot: 0,
|
||||
latest_custody_reseed_slot: Slot::from(0_u64),
|
||||
penultimate_custody_reseed_slot: Slot::from(0_u64),
|
||||
};
|
||||
initial_validators.push(validator);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
mod foundation;
|
||||
|
||||
use crate::{Address, Eth1Data, Hash256, Validator};
|
||||
use crate::{Address, Eth1Data, Hash256, Slot, Validator};
|
||||
use bls::Signature;
|
||||
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
@ -29,9 +29,9 @@ pub struct ChainSpec {
|
||||
* Initial Values
|
||||
*/
|
||||
pub genesis_fork_version: u64,
|
||||
pub genesis_slot: u64,
|
||||
pub genesis_slot: Slot,
|
||||
pub genesis_start_shard: u64,
|
||||
pub far_future_slot: u64,
|
||||
pub far_future_slot: Slot,
|
||||
pub zero_hash: Hash256,
|
||||
pub empty_signature: Signature,
|
||||
pub bls_withdrawal_prefix_byte: u8,
|
||||
|
@ -1,9 +1,10 @@
|
||||
/// Contains logic to manipulate a `&[Validator]`.
|
||||
/// For now, we avoid defining a newtype and just have flat functions here.
|
||||
use super::validator::*;
|
||||
use crate::Slot;
|
||||
|
||||
/// Given an indexed sequence of `validators`, return the indices corresponding to validators that are active at `slot`.
|
||||
pub fn get_active_validator_indices(validators: &[Validator], slot: u64) -> Vec<usize> {
|
||||
pub fn get_active_validator_indices(validators: &[Validator], slot: Slot) -> Vec<usize> {
|
||||
validators
|
||||
.iter()
|
||||
.enumerate()
|
||||
@ -27,7 +28,7 @@ mod tests {
|
||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||
|
||||
let validators = vec![];
|
||||
let some_slot = u64::random_for_test(&mut rng);
|
||||
let some_slot = Slot::random_for_test(&mut rng);
|
||||
let indices = get_active_validator_indices(&validators, some_slot);
|
||||
assert_eq!(indices, vec![]);
|
||||
}
|
||||
@ -41,7 +42,7 @@ mod tests {
|
||||
validators.push(Validator::default())
|
||||
}
|
||||
|
||||
let some_slot = u64::random_for_test(&mut rng);
|
||||
let some_slot = Slot::random_for_test(&mut rng);
|
||||
let indices = get_active_validator_indices(&validators, some_slot);
|
||||
assert_eq!(indices, vec![]);
|
||||
}
|
||||
@ -50,7 +51,7 @@ mod tests {
|
||||
fn can_get_all_active_validator_indices() {
|
||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||
let count_validators = 10;
|
||||
let some_slot = u64::random_for_test(&mut rng);
|
||||
let some_slot = Slot::random_for_test(&mut rng);
|
||||
|
||||
let mut validators = (0..count_validators)
|
||||
.into_iter()
|
||||
@ -60,8 +61,8 @@ mod tests {
|
||||
let activation_offset = u64::random_for_test(&mut rng);
|
||||
let exit_offset = u64::random_for_test(&mut rng);
|
||||
|
||||
validator.activation_slot = some_slot.checked_sub(activation_offset).unwrap_or(0);
|
||||
validator.exit_slot = some_slot.checked_add(exit_offset).unwrap_or(std::u64::MAX);
|
||||
validator.activation_slot = some_slot - activation_offset;
|
||||
validator.exit_slot = some_slot + exit_offset;
|
||||
|
||||
validator
|
||||
})
|
||||
@ -81,13 +82,13 @@ mod tests {
|
||||
|
||||
fn set_validators_to_default_entry_exit(validators: &mut [Validator]) {
|
||||
for validator in validators.iter_mut() {
|
||||
validator.activation_slot = std::u64::MAX;
|
||||
validator.exit_slot = std::u64::MAX;
|
||||
validator.activation_slot = Slot::max_value();
|
||||
validator.exit_slot = Slot::max_value();
|
||||
}
|
||||
}
|
||||
|
||||
// sets all `validators` to be active as of some slot prior to `slot`. returns the activation slot.
|
||||
fn set_validators_to_activated(validators: &mut [Validator], slot: u64) -> u64 {
|
||||
fn set_validators_to_activated(validators: &mut [Validator], slot: Slot) -> Slot {
|
||||
let activation_slot = slot - 10;
|
||||
for validator in validators.iter_mut() {
|
||||
validator.activation_slot = activation_slot;
|
||||
@ -96,7 +97,7 @@ mod tests {
|
||||
}
|
||||
|
||||
// sets all `validators` to be exited as of some slot before `slot`.
|
||||
fn set_validators_to_exited(validators: &mut [Validator], slot: u64, activation_slot: u64) {
|
||||
fn set_validators_to_exited(validators: &mut [Validator], slot: Slot, activation_slot: Slot) {
|
||||
assert!(activation_slot < slot);
|
||||
let mut exit_slot = activation_slot + 10;
|
||||
while exit_slot >= slot {
|
||||
@ -114,18 +115,18 @@ mod tests {
|
||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||
const COUNT_PARTITIONS: usize = 3;
|
||||
const COUNT_VALIDATORS: usize = 3 * COUNT_PARTITIONS;
|
||||
let some_slot: u64 = u64::random_for_test(&mut rng);
|
||||
let some_slot: Slot = Slot::random_for_test(&mut rng);
|
||||
|
||||
let mut validators = (0..COUNT_VALIDATORS)
|
||||
.into_iter()
|
||||
.map(|_| {
|
||||
let mut validator = Validator::default();
|
||||
|
||||
let activation_offset = u64::random_for_test(&mut rng);
|
||||
let exit_offset = u64::random_for_test(&mut rng);
|
||||
let activation_offset = Slot::random_for_test(&mut rng);
|
||||
let exit_offset = Slot::random_for_test(&mut rng);
|
||||
|
||||
validator.activation_slot = some_slot.checked_sub(activation_offset).unwrap_or(0);
|
||||
validator.exit_slot = some_slot.checked_add(exit_offset).unwrap_or(std::u64::MAX);
|
||||
validator.activation_slot = some_slot - activation_offset;
|
||||
validator.exit_slot = some_slot + exit_offset;
|
||||
|
||||
validator
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user