Fix all compile errors from new Slot/Epoch types

This commit is contained in:
Paul Hauner
2019-02-07 11:22:48 +11:00
parent 9b1d8cd3c1
commit 85450ec254
30 changed files with 177 additions and 135 deletions

View File

@@ -3,7 +3,7 @@ mod traits;
use slot_clock::SlotClock;
use std::sync::Arc;
use types::{AttestationData, FreeAttestation, Signature};
use types::{AttestationData, FreeAttestation, Signature, Slot};
pub use self::traits::{
BeaconNode, BeaconNodeError, DutiesReader, DutiesReaderError, PublishOutcome, Signer,
@@ -13,14 +13,14 @@ const PHASE_0_CUSTODY_BIT: bool = false;
#[derive(Debug, PartialEq)]
pub enum PollOutcome {
AttestationProduced(u64),
AttestationNotRequired(u64),
SlashableAttestationNotProduced(u64),
BeaconNodeUnableToProduceAttestation(u64),
ProducerDutiesUnknown(u64),
SlotAlreadyProcessed(u64),
SignerRejection(u64),
ValidatorIsUnknown(u64),
AttestationProduced(Slot),
AttestationNotRequired(Slot),
SlashableAttestationNotProduced(Slot),
BeaconNodeUnableToProduceAttestation(Slot),
ProducerDutiesUnknown(Slot),
SlotAlreadyProcessed(Slot),
SignerRejection(Slot),
ValidatorIsUnknown(Slot),
}
#[derive(Debug, PartialEq)]
@@ -40,7 +40,7 @@ pub enum Error {
///
/// Relies upon an external service to keep the `EpochDutiesMap` updated.
pub struct Attester<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> {
pub last_processed_slot: Option<u64>,
pub last_processed_slot: Option<Slot>,
duties: Arc<V>,
slot_clock: Arc<T>,
beacon_node: Arc<U>,
@@ -91,7 +91,7 @@ impl<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> Attester<T, U, V,
}
}
fn produce_attestation(&mut self, slot: u64, shard: u64) -> Result<PollOutcome, Error> {
fn produce_attestation(&mut self, slot: Slot, shard: u64) -> Result<PollOutcome, Error> {
let attestation_data = match self.beacon_node.produce_attestation_data(slot, shard)? {
Some(attestation_data) => attestation_data,
None => return Ok(PollOutcome::BeaconNodeUnableToProduceAttestation(slot)),
@@ -122,7 +122,7 @@ impl<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> Attester<T, U, V,
Ok(PollOutcome::AttestationProduced(slot))
}
fn is_processed_slot(&self, slot: u64) -> bool {
fn is_processed_slot(&self, slot: Slot) -> bool {
match self.last_processed_slot {
Some(processed_slot) if slot <= processed_slot => true,
_ => false,
@@ -193,7 +193,7 @@ mod tests {
let signer = Arc::new(LocalSigner::new(Keypair::random()));
let mut duties = EpochMap::new(spec.epoch_length);
let attest_slot = 100;
let attest_slot = Slot::new(100);
let attest_epoch = attest_slot / spec.epoch_length;
let attest_shard = 12;
duties.insert_attestation_shard(attest_slot, attest_shard);
@@ -212,28 +212,28 @@ mod tests {
beacon_node.set_next_publish_result(Ok(PublishOutcome::ValidAttestation));
// One slot before attestation slot...
slot_clock.set_slot(attest_slot - 1);
slot_clock.set_slot(attest_slot.as_u64() - 1);
assert_eq!(
attester.poll(),
Ok(PollOutcome::AttestationNotRequired(attest_slot - 1))
);
// On the attest slot...
slot_clock.set_slot(attest_slot);
slot_clock.set_slot(attest_slot.as_u64());
assert_eq!(
attester.poll(),
Ok(PollOutcome::AttestationProduced(attest_slot))
);
// Trying the same attest slot again...
slot_clock.set_slot(attest_slot);
slot_clock.set_slot(attest_slot.as_u64());
assert_eq!(
attester.poll(),
Ok(PollOutcome::SlotAlreadyProcessed(attest_slot))
);
// One slot after the attest slot...
slot_clock.set_slot(attest_slot + 1);
slot_clock.set_slot(attest_slot.as_u64() + 1);
assert_eq!(
attester.poll(),
Ok(PollOutcome::AttestationNotRequired(attest_slot + 1))
@@ -241,7 +241,7 @@ mod tests {
// In an epoch without known duties...
let slot = (attest_epoch + 1) * spec.epoch_length;
slot_clock.set_slot(slot);
slot_clock.set_slot(slot.into());
assert_eq!(
attester.poll(),
Ok(PollOutcome::ProducerDutiesUnknown(slot))

View File

@@ -1,10 +1,11 @@
use crate::{DutiesReader, DutiesReaderError};
use std::collections::HashMap;
use types::{Epoch, Slot};
pub struct EpochMap {
epoch_length: u64,
validator_index: Option<u64>,
map: HashMap<u64, (u64, u64)>,
map: HashMap<Epoch, (Slot, u64)>,
}
impl EpochMap {
@@ -16,9 +17,8 @@ impl EpochMap {
}
}
pub fn insert_attestation_shard(&mut self, slot: u64, shard: u64) {
let epoch = slot / self.epoch_length;
pub fn insert_attestation_shard(&mut self, slot: Slot, shard: u64) {
let epoch = slot.epoch(self.epoch_length);
self.map.insert(epoch, (slot, shard));
}
@@ -28,8 +28,8 @@ impl EpochMap {
}
impl DutiesReader for EpochMap {
fn attestation_shard(&self, slot: u64) -> Result<Option<u64>, DutiesReaderError> {
let epoch = slot / self.epoch_length;
fn attestation_shard(&self, slot: Slot) -> Result<Option<u64>, DutiesReaderError> {
let epoch = slot.epoch(self.epoch_length);
match self.map.get(&epoch) {
Some((attest_slot, attest_shard)) if *attest_slot == slot => Ok(Some(*attest_shard)),

View File

@@ -1,6 +1,6 @@
use crate::traits::{BeaconNode, BeaconNodeError, PublishOutcome};
use std::sync::RwLock;
use types::{AttestationData, FreeAttestation};
use types::{AttestationData, FreeAttestation, Slot};
type ProduceResult = Result<Option<AttestationData>, BeaconNodeError>;
type PublishResult = Result<PublishOutcome, BeaconNodeError>;
@@ -8,7 +8,7 @@ type PublishResult = Result<PublishOutcome, BeaconNodeError>;
/// A test-only struct used to simulate a Beacon Node.
#[derive(Default)]
pub struct SimulatedBeaconNode {
pub produce_input: RwLock<Option<(u64, u64)>>,
pub produce_input: RwLock<Option<(Slot, u64)>>,
pub produce_result: RwLock<Option<ProduceResult>>,
pub publish_input: RwLock<Option<FreeAttestation>>,
@@ -26,7 +26,7 @@ impl SimulatedBeaconNode {
}
impl BeaconNode for SimulatedBeaconNode {
fn produce_attestation_data(&self, slot: u64, shard: u64) -> ProduceResult {
fn produce_attestation_data(&self, slot: Slot, shard: u64) -> ProduceResult {
*self.produce_input.write().unwrap() = Some((slot, shard));
match *self.produce_result.read().unwrap() {
Some(ref r) => r.clone(),

View File

@@ -1,4 +1,4 @@
use types::{AttestationData, FreeAttestation, Signature};
use types::{AttestationData, FreeAttestation, Signature, Slot};
#[derive(Debug, PartialEq, Clone)]
pub enum BeaconNodeError {
@@ -16,7 +16,7 @@ pub enum PublishOutcome {
pub trait BeaconNode: Send + Sync {
fn produce_attestation_data(
&self,
slot: u64,
slot: Slot,
shard: u64,
) -> Result<Option<AttestationData>, BeaconNodeError>;
@@ -37,7 +37,7 @@ pub enum DutiesReaderError {
/// Informs a validator of their duties (e.g., block production).
pub trait DutiesReader: Send + Sync {
/// Returns `Some(shard)` if this slot is an attestation slot. Otherwise, returns `None.`
fn attestation_shard(&self, slot: u64) -> Result<Option<u64>, DutiesReaderError>;
fn attestation_shard(&self, slot: Slot) -> Result<Option<u64>, DutiesReaderError>;
/// Returns `Some(shard)` if this slot is an attestation slot. Otherwise, returns `None.`
fn validator_index(&self) -> Option<u64>;

View File

@@ -4,7 +4,7 @@ mod traits;
use slot_clock::SlotClock;
use ssz::ssz_encode;
use std::sync::Arc;
use types::{BeaconBlock, ChainSpec, PublicKey};
use types::{BeaconBlock, ChainSpec, PublicKey, Slot};
pub use self::traits::{
BeaconNode, BeaconNodeError, DutiesReader, DutiesReaderError, PublishOutcome, Signer,
@@ -13,21 +13,21 @@ pub use self::traits::{
#[derive(Debug, PartialEq)]
pub enum PollOutcome {
/// A new block was produced.
BlockProduced(u64),
BlockProduced(Slot),
/// A block was not produced as it would have been slashable.
SlashableBlockNotProduced(u64),
SlashableBlockNotProduced(Slot),
/// The validator duties did not require a block to be produced.
BlockProductionNotRequired(u64),
BlockProductionNotRequired(Slot),
/// The duties for the present epoch were not found.
ProducerDutiesUnknown(u64),
ProducerDutiesUnknown(Slot),
/// The slot has already been processed, execution was skipped.
SlotAlreadyProcessed(u64),
SlotAlreadyProcessed(Slot),
/// The Beacon Node was unable to produce a block at that slot.
BeaconNodeUnableToProduceBlock(u64),
BeaconNodeUnableToProduceBlock(Slot),
/// The signer failed to sign the message.
SignerRejection(u64),
SignerRejection(Slot),
/// The public key for this validator is not an active validator.
ValidatorIsUnknown(u64),
ValidatorIsUnknown(Slot),
}
#[derive(Debug, PartialEq)]
@@ -47,7 +47,7 @@ pub enum Error {
///
/// Relies upon an external service to keep the `EpochDutiesMap` updated.
pub struct BlockProducer<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> {
pub last_processed_slot: Option<u64>,
pub last_processed_slot: Option<Slot>,
pubkey: PublicKey,
spec: Arc<ChainSpec>,
epoch_map: Arc<V>,
@@ -115,7 +115,7 @@ impl<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> BlockProducer<T, U
}
}
fn is_processed_slot(&self, slot: u64) -> bool {
fn is_processed_slot(&self, slot: Slot) -> bool {
match self.last_processed_slot {
Some(processed_slot) if processed_slot >= slot => true,
_ => false,
@@ -132,7 +132,7 @@ impl<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> BlockProducer<T, U
///
/// The slash-protection code is not yet implemented. There is zero protection against
/// slashing.
fn produce_block(&mut self, slot: u64) -> Result<PollOutcome, Error> {
fn produce_block(&mut self, slot: Slot) -> Result<PollOutcome, Error> {
let randao_reveal = {
let producer_nonce = self.beacon_node.proposer_nonce(&self.pubkey)?;
@@ -236,8 +236,8 @@ mod tests {
let signer = Arc::new(LocalSigner::new(Keypair::random()));
let mut epoch_map = EpochMap::new(spec.epoch_length);
let produce_slot = 100;
let produce_epoch = produce_slot / spec.epoch_length;
let produce_slot = Slot::new(100);
let produce_epoch = produce_slot.epoch(spec.epoch_length);
epoch_map.map.insert(produce_epoch, produce_slot);
let epoch_map = Arc::new(epoch_map);
let keypair = Keypair::random();
@@ -257,39 +257,39 @@ mod tests {
beacon_node.set_next_nonce_result(Ok(0));
// One slot before production slot...
slot_clock.set_slot(produce_slot - 1);
slot_clock.set_slot(produce_slot.as_u64() - 1);
assert_eq!(
block_producer.poll(),
Ok(PollOutcome::BlockProductionNotRequired(produce_slot - 1))
);
// On the produce slot...
slot_clock.set_slot(produce_slot);
slot_clock.set_slot(produce_slot.as_u64());
assert_eq!(
block_producer.poll(),
Ok(PollOutcome::BlockProduced(produce_slot))
Ok(PollOutcome::BlockProduced(produce_slot.into()))
);
// Trying the same produce slot again...
slot_clock.set_slot(produce_slot);
slot_clock.set_slot(produce_slot.as_u64());
assert_eq!(
block_producer.poll(),
Ok(PollOutcome::SlotAlreadyProcessed(produce_slot))
);
// One slot after the produce slot...
slot_clock.set_slot(produce_slot + 1);
slot_clock.set_slot(produce_slot.as_u64() + 1);
assert_eq!(
block_producer.poll(),
Ok(PollOutcome::BlockProductionNotRequired(produce_slot + 1))
);
// In an epoch without known duties...
let slot = (produce_epoch + 1) * spec.epoch_length;
let slot = (produce_epoch.as_u64() + 1) * spec.epoch_length;
slot_clock.set_slot(slot);
assert_eq!(
block_producer.poll(),
Ok(PollOutcome::ProducerDutiesUnknown(slot))
Ok(PollOutcome::ProducerDutiesUnknown(Slot::new(slot)))
);
}
}

View File

@@ -1,9 +1,10 @@
use crate::{DutiesReader, DutiesReaderError};
use std::collections::HashMap;
use types::{Epoch, Slot};
pub struct EpochMap {
epoch_length: u64,
pub map: HashMap<u64, u64>,
pub map: HashMap<Epoch, Slot>,
}
impl EpochMap {
@@ -16,8 +17,8 @@ impl EpochMap {
}
impl DutiesReader for EpochMap {
fn is_block_production_slot(&self, slot: u64) -> Result<bool, DutiesReaderError> {
let epoch = slot / self.epoch_length;
fn is_block_production_slot(&self, slot: Slot) -> Result<bool, DutiesReaderError> {
let epoch = slot.epoch(self.epoch_length);
match self.map.get(&epoch) {
Some(s) if *s == slot => Ok(true),
Some(s) if *s != slot => Ok(false),

View File

@@ -1,6 +1,6 @@
use crate::traits::{BeaconNode, BeaconNodeError, PublishOutcome};
use std::sync::RwLock;
use types::{BeaconBlock, PublicKey, Signature};
use types::{BeaconBlock, PublicKey, Signature, Slot};
type NonceResult = Result<u64, BeaconNodeError>;
type ProduceResult = Result<Option<BeaconBlock>, BeaconNodeError>;
@@ -12,7 +12,7 @@ pub struct SimulatedBeaconNode {
pub nonce_input: RwLock<Option<PublicKey>>,
pub nonce_result: RwLock<Option<NonceResult>>,
pub produce_input: RwLock<Option<(u64, Signature)>>,
pub produce_input: RwLock<Option<(Slot, Signature)>>,
pub produce_result: RwLock<Option<ProduceResult>>,
pub publish_input: RwLock<Option<BeaconBlock>>,
@@ -46,7 +46,7 @@ impl BeaconNode for SimulatedBeaconNode {
}
/// Returns the value specified by the `set_next_produce_result`.
fn produce_beacon_block(&self, slot: u64, randao_reveal: &Signature) -> ProduceResult {
fn produce_beacon_block(&self, slot: Slot, randao_reveal: &Signature) -> ProduceResult {
*self.produce_input.write().unwrap() = Some((slot, randao_reveal.clone()));
match *self.produce_result.read().unwrap() {
Some(ref r) => r.clone(),

View File

@@ -1,4 +1,4 @@
use types::{BeaconBlock, PublicKey, Signature};
use types::{BeaconBlock, PublicKey, Signature, Slot};
#[derive(Debug, PartialEq, Clone)]
pub enum BeaconNodeError {
@@ -22,7 +22,7 @@ pub trait BeaconNode: Send + Sync {
/// Returns Ok(None) if the Beacon Node is unable to produce at the given slot.
fn produce_beacon_block(
&self,
slot: u64,
slot: Slot,
randao_reveal: &Signature,
) -> Result<Option<BeaconBlock>, BeaconNodeError>;
@@ -42,7 +42,7 @@ pub enum DutiesReaderError {
/// Informs a validator of their duties (e.g., block production).
pub trait DutiesReader: Send + Sync {
fn is_block_production_slot(&self, slot: u64) -> Result<bool, DutiesReaderError>;
fn is_block_production_slot(&self, slot: Slot) -> Result<bool, DutiesReaderError>;
}
/// Signs message using an internally-maintained private key.

View File

@@ -6,7 +6,7 @@ use db::stores::BeaconBlockStore;
use db::{ClientDB, DBError};
use ssz::{Decodable, DecodeError};
use std::sync::Arc;
use types::{BeaconBlock, Hash256};
use types::{BeaconBlock, Hash256, Slot};
pub enum ForkChoiceError {
BadSszInDatabase,
@@ -37,7 +37,7 @@ where
/*
* Loop through all the head blocks and find the highest slot.
*/
let highest_slot: Option<u64> = None;
let highest_slot: Option<Slot> = None;
for (_, block) in &head_blocks {
let slot = block.slot;

View File

@@ -17,5 +17,6 @@ rand = "0.5.5"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
slog = "^2.2.3"
ssz = { path = "../utils/ssz" }
vec_shuffle = { path = "../utils/vec_shuffle" }

View File

@@ -12,6 +12,7 @@
use crate::test_utils::TestRandom;
use rand::RngCore;
use serde_derive::Serialize;
use slog;
use ssz::{hash, Decodable, DecodeError, Encodable, SszStream, TreeHash};
use std::cmp::{Ord, Ordering};
use std::fmt;
@@ -162,6 +163,15 @@ macro_rules! impl_math {
*self - other.into()
}
pub fn checked_div<T: Into<$type>>(&self, rhs: T) -> Option<$type> {
let rhs: $type = rhs.into();
if rhs == 0 {
None
} else {
Some(*self / rhs)
}
}
pub fn is_power_of_two(&self) -> bool {
self.0.is_power_of_two()
}
@@ -183,6 +193,17 @@ macro_rules! impl_display {
write!(f, "{}", self.0)
}
}
impl slog::Value for $type {
fn serialize(
&self,
record: &slog::Record,
key: slog::Key,
serializer: &mut slog::Serializer,
) -> slog::Result {
self.0.serialize(record, key, serializer)
}
}
};
}

View File

@@ -109,7 +109,7 @@ fn initial_validators_for_testing() -> Vec<Validator> {
let validator = Validator {
pubkey: keypair.pk.clone(),
withdrawal_credentials: Hash256::zero(),
proposer_slots: Slot::from(0_u64),
proposer_slots: 0,
activation_slot: Slot::max_value(),
exit_slot: Slot::max_value(),
withdrawal_slot: Slot::max_value(),

View File

@@ -46,7 +46,7 @@ fn status_flag_from_byte(flag: u8) -> Result<Option<StatusFlags>, StatusFlagsDec
pub struct Validator {
pub pubkey: PublicKey,
pub withdrawal_credentials: Hash256,
pub proposer_slots: Slot,
pub proposer_slots: u64,
pub activation_slot: Slot,
pub exit_slot: Slot,
pub withdrawal_slot: Slot,
@@ -70,7 +70,7 @@ impl Default for Validator {
Self {
pubkey: PublicKey::default(),
withdrawal_credentials: Hash256::default(),
proposer_slots: Slot::from(0_u64),
proposer_slots: 0,
activation_slot: Slot::from(std::u64::MAX),
exit_slot: Slot::from(std::u64::MAX),
withdrawal_slot: Slot::from(std::u64::MAX),

View File

@@ -5,3 +5,4 @@ authors = ["Paul Hauner <paul@paulhauner.com>"]
edition = "2018"
[dependencies]
types = { path = "../../types" }

View File

@@ -3,9 +3,10 @@ mod testing_slot_clock;
pub use crate::system_time_slot_clock::{Error as SystemTimeSlotClockError, SystemTimeSlotClock};
pub use crate::testing_slot_clock::{Error as TestingSlotClockError, TestingSlotClock};
pub use types::Slot;
pub trait SlotClock: Send + Sync {
type Error;
fn present_slot(&self) -> Result<Option<u64>, Self::Error>;
fn present_slot(&self) -> Result<Option<Slot>, Self::Error>;
}

View File

@@ -1,5 +1,6 @@
use super::SlotClock;
use std::time::{Duration, SystemTime};
use types::Slot;
pub use std::time::SystemTimeError;
@@ -38,7 +39,7 @@ impl SystemTimeSlotClock {
impl SlotClock for SystemTimeSlotClock {
type Error = Error;
fn present_slot(&self) -> Result<Option<u64>, Error> {
fn present_slot(&self) -> Result<Option<Slot>, Error> {
let syslot_time = SystemTime::now();
let duration_since_epoch = syslot_time.duration_since(SystemTime::UNIX_EPOCH)?;
let duration_since_genesis =
@@ -56,8 +57,10 @@ impl From<SystemTimeError> for Error {
}
}
fn slot_from_duration(slot_duration_seconds: u64, duration: Duration) -> Option<u64> {
duration.as_secs().checked_div(slot_duration_seconds)
fn slot_from_duration(slot_duration_seconds: u64, duration: Duration) -> Option<Slot> {
Some(Slot::new(
duration.as_secs().checked_div(slot_duration_seconds)?,
))
}
#[cfg(test)]
@@ -81,19 +84,19 @@ mod tests {
genesis_seconds: genesis,
slot_duration_seconds: slot_time,
};
assert_eq!(clock.present_slot().unwrap(), Some(89));
assert_eq!(clock.present_slot().unwrap(), Some(Slot::new(89)));
let clock = SystemTimeSlotClock {
genesis_seconds: since_epoch.as_secs(),
slot_duration_seconds: slot_time,
};
assert_eq!(clock.present_slot().unwrap(), Some(0));
assert_eq!(clock.present_slot().unwrap(), Some(Slot::new(0)));
let clock = SystemTimeSlotClock {
genesis_seconds: since_epoch.as_secs() - slot_time * 42 - 5,
slot_duration_seconds: slot_time,
};
assert_eq!(clock.present_slot().unwrap(), Some(42));
assert_eq!(clock.present_slot().unwrap(), Some(Slot::new(42)));
}
#[test]
@@ -102,23 +105,23 @@ mod tests {
assert_eq!(
slot_from_duration(slot_time, Duration::from_secs(0)),
Some(0)
Some(Slot::new(0))
);
assert_eq!(
slot_from_duration(slot_time, Duration::from_secs(10)),
Some(0)
Some(Slot::new(0))
);
assert_eq!(
slot_from_duration(slot_time, Duration::from_secs(100)),
Some(1)
Some(Slot::new(1))
);
assert_eq!(
slot_from_duration(slot_time, Duration::from_secs(101)),
Some(1)
Some(Slot::new(1))
);
assert_eq!(
slot_from_duration(slot_time, Duration::from_secs(1000)),
Some(10)
Some(Slot::new(10))
);
}

View File

@@ -1,5 +1,6 @@
use super::SlotClock;
use std::sync::RwLock;
use types::Slot;
#[derive(Debug, PartialEq)]
pub enum Error {}
@@ -27,9 +28,9 @@ impl TestingSlotClock {
impl SlotClock for TestingSlotClock {
type Error = Error;
fn present_slot(&self) -> Result<Option<u64>, Error> {
fn present_slot(&self) -> Result<Option<Slot>, Error> {
let slot = *self.slot.read().expect("TestingSlotClock poisoned.");
Ok(Some(slot))
Ok(Some(Slot::new(slot)))
}
}
@@ -40,8 +41,8 @@ mod tests {
#[test]
fn test_slot_now() {
let clock = TestingSlotClock::new(10);
assert_eq!(clock.present_slot(), Ok(Some(10)));
assert_eq!(clock.present_slot(), Ok(Some(Slot::new(10))));
clock.set_slot(123);
assert_eq!(clock.present_slot(), Ok(Some(123)));
assert_eq!(clock.present_slot(), Ok(Some(Slot::new(123))));
}
}

View File

@@ -41,7 +41,7 @@ pub fn process_deposit(
let validator = Validator {
pubkey: deposit_input.pubkey.clone(),
withdrawal_credentials: deposit_input.withdrawal_credentials,
proposer_slots: Slot::new(0),
proposer_slots: 0,
activation_slot: spec.far_future_slot,
exit_slot: spec.far_future_slot,
withdrawal_slot: spec.far_future_slot,