From 85450ec254aff50941c62393f86780f2a61653f6 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Thu, 7 Feb 2019 11:22:48 +1100 Subject: [PATCH] Fix all compile errors from new Slot/Epoch types --- beacon_node/beacon_chain/src/beacon_chain.rs | 4 +- .../test_harness/src/beacon_chain_harness.rs | 10 ++--- .../validator_harness/direct_beacon_node.rs | 6 +-- .../src/validator_harness/direct_duties.rs | 6 +-- .../validator_harness/validator_harness.rs | 8 ++-- .../beacon_chain/test_harness/tests/chain.rs | 4 +- eth2/attester/src/lib.rs | 36 ++++++++-------- eth2/attester/src/test_utils/epoch_map.rs | 12 +++--- .../src/test_utils/simulated_beacon_node.rs | 6 +-- eth2/attester/src/traits.rs | 6 +-- eth2/block_producer/src/lib.rs | 42 +++++++++---------- .../src/test_utils/epoch_map.rs | 7 ++-- .../src/test_utils/simulated_beacon_node.rs | 6 +-- eth2/block_producer/src/traits.rs | 6 +-- eth2/naive_fork_choice/src/lib.rs | 4 +- eth2/types/Cargo.toml | 1 + eth2/types/src/slot_epoch.rs | 21 ++++++++++ eth2/types/src/spec/foundation.rs | 2 +- eth2/types/src/validator.rs | 4 +- eth2/utils/slot_clock/Cargo.toml | 1 + eth2/utils/slot_clock/src/lib.rs | 3 +- .../slot_clock/src/system_time_slot_clock.rs | 25 ++++++----- .../slot_clock/src/testing_slot_clock.rs | 9 ++-- eth2/validator_induction/src/inductor.rs | 2 +- .../beacon_block_grpc_client.rs | 10 ++--- validator_client/src/duties/epoch_duties.rs | 17 ++++---- validator_client/src/duties/grpc.rs | 11 +++-- validator_client/src/duties/mod.rs | 35 +++++++++------- validator_client/src/duties/test_node.rs | 5 ++- validator_client/src/duties/traits.rs | 3 +- 30 files changed, 177 insertions(+), 135 deletions(-) diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index 8d821259f..cde4d7cf6 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -230,7 +230,7 @@ where /// Returns `None` if the `validator_index` is invalid. /// /// Information is retrieved from the present `beacon_state.validator_registry`. - pub fn proposer_slots(&self, validator_index: usize) -> Option { + pub fn proposer_slots(&self, validator_index: usize) -> Option { if let Some(validator) = self.state.read().validator_registry.get(validator_index) { Some(validator.proposer_slots) } else { @@ -248,7 +248,7 @@ where /// `self.state` should undergo per slot processing. pub fn read_slot_clock(&self) -> Option { match self.slot_clock.present_slot() { - Ok(Some(some_slot)) => Some(Slot::new(some_slot)), + Ok(Some(some_slot)) => Some(some_slot), Ok(None) => None, _ => None, } diff --git a/beacon_node/beacon_chain/test_harness/src/beacon_chain_harness.rs b/beacon_node/beacon_chain/test_harness/src/beacon_chain_harness.rs index 64d18b4be..7cfe65b39 100644 --- a/beacon_node/beacon_chain/test_harness/src/beacon_chain_harness.rs +++ b/beacon_node/beacon_chain/test_harness/src/beacon_chain_harness.rs @@ -13,7 +13,7 @@ use std::fs::File; use std::io::prelude::*; use std::iter::FromIterator; use std::sync::Arc; -use types::{BeaconBlock, ChainSpec, FreeAttestation, Keypair, Validator}; +use types::{BeaconBlock, ChainSpec, FreeAttestation, Keypair, Slot, Validator}; /// The beacon chain harness simulates a single beacon node with `validator_count` validators connected /// to it. Each validator is provided a borrow to the beacon chain, where it may read @@ -40,7 +40,7 @@ impl BeaconChainHarness { let block_store = Arc::new(BeaconBlockStore::new(db.clone())); let state_store = Arc::new(BeaconStateStore::new(db.clone())); - let slot_clock = TestingSlotClock::new(spec.genesis_slot); + let slot_clock = TestingSlotClock::new(spec.genesis_slot.as_u64()); // Remove the validators present in the spec (if any). spec.initial_validators = Vec::with_capacity(validator_count); @@ -60,7 +60,7 @@ impl BeaconChainHarness { .par_iter() .map(|keypair| Validator { pubkey: keypair.pk.clone(), - activation_slot: 0, + activation_slot: Slot::new(0), ..std::default::Default::default() }) .collect(); @@ -115,12 +115,12 @@ impl BeaconChainHarness { /// This is the equivalent of advancing a system clock forward one `SLOT_DURATION`. /// /// Returns the new slot. - pub fn increment_beacon_chain_slot(&mut self) -> u64 { + pub fn increment_beacon_chain_slot(&mut self) -> Slot { let slot = self.beacon_chain.present_slot() + 1; debug!("Incrementing BeaconChain slot to {}.", slot); - self.beacon_chain.slot_clock.set_slot(slot); + self.beacon_chain.slot_clock.set_slot(slot.as_u64()); self.beacon_chain.advance_state(slot).unwrap(); slot } diff --git a/beacon_node/beacon_chain/test_harness/src/validator_harness/direct_beacon_node.rs b/beacon_node/beacon_chain/test_harness/src/validator_harness/direct_beacon_node.rs index ed71f28d3..f33eb65e8 100644 --- a/beacon_node/beacon_chain/test_harness/src/validator_harness/direct_beacon_node.rs +++ b/beacon_node/beacon_chain/test_harness/src/validator_harness/direct_beacon_node.rs @@ -11,7 +11,7 @@ use db::ClientDB; use parking_lot::RwLock; use slot_clock::SlotClock; use std::sync::Arc; -use types::{AttestationData, BeaconBlock, FreeAttestation, PublicKey, Signature}; +use types::{AttestationData, BeaconBlock, FreeAttestation, PublicKey, Signature, Slot}; // mod attester; // mod producer; @@ -51,7 +51,7 @@ impl DirectBeaconNode { impl AttesterBeaconNode for DirectBeaconNode { fn produce_attestation_data( &self, - _slot: u64, + _slot: Slot, shard: u64, ) -> Result, NodeError> { match self.beacon_chain.produce_attestation_data(shard) { @@ -87,7 +87,7 @@ impl BeaconBlockNode for DirectBeaconNode { /// Requests a new `BeaconBlock from the `BeaconChain`. fn produce_beacon_block( &self, - slot: u64, + slot: Slot, randao_reveal: &Signature, ) -> Result, BeaconBlockNodeError> { let (block, _state) = self diff --git a/beacon_node/beacon_chain/test_harness/src/validator_harness/direct_duties.rs b/beacon_node/beacon_chain/test_harness/src/validator_harness/direct_duties.rs index e724b3e55..eac56679b 100644 --- a/beacon_node/beacon_chain/test_harness/src/validator_harness/direct_duties.rs +++ b/beacon_node/beacon_chain/test_harness/src/validator_harness/direct_duties.rs @@ -8,7 +8,7 @@ use block_producer::{ use db::ClientDB; use slot_clock::SlotClock; use std::sync::Arc; -use types::PublicKey; +use types::{PublicKey, Slot}; /// Connects directly to a borrowed `BeaconChain` and reads attester/proposer duties directly from /// it. @@ -27,7 +27,7 @@ impl DirectDuties { } impl ProducerDutiesReader for DirectDuties { - fn is_block_production_slot(&self, slot: u64) -> Result { + fn is_block_production_slot(&self, slot: Slot) -> Result { let validator_index = self .beacon_chain .validator_index(&self.pubkey) @@ -49,7 +49,7 @@ impl AttesterDutiesReader for DirectDuties { } } - fn attestation_shard(&self, slot: u64) -> Result, AttesterDutiesReaderError> { + fn attestation_shard(&self, slot: Slot) -> Result, AttesterDutiesReaderError> { if let Some(validator_index) = self.validator_index() { match self .beacon_chain diff --git a/beacon_node/beacon_chain/test_harness/src/validator_harness/validator_harness.rs b/beacon_node/beacon_chain/test_harness/src/validator_harness/validator_harness.rs index 986d843bb..5ffcc5a4a 100644 --- a/beacon_node/beacon_chain/test_harness/src/validator_harness/validator_harness.rs +++ b/beacon_node/beacon_chain/test_harness/src/validator_harness/validator_harness.rs @@ -9,7 +9,7 @@ use block_producer::{BlockProducer, Error as BlockPollError}; use db::MemoryDB; use slot_clock::TestingSlotClock; use std::sync::Arc; -use types::{BeaconBlock, ChainSpec, FreeAttestation, Keypair}; +use types::{BeaconBlock, ChainSpec, FreeAttestation, Keypair, Slot}; #[derive(Debug, PartialEq)] pub enum BlockProduceError { @@ -59,7 +59,7 @@ impl ValidatorHarness { beacon_chain: Arc>, spec: Arc, ) -> Self { - let slot_clock = Arc::new(TestingSlotClock::new(spec.genesis_slot)); + let slot_clock = Arc::new(TestingSlotClock::new(spec.genesis_slot.as_u64())); let signer = Arc::new(LocalSigner::new(keypair.clone())); let beacon_node = Arc::new(DirectBeaconNode::new(beacon_chain.clone())); let epoch_map = Arc::new(DirectDuties::new(keypair.pk.clone(), beacon_chain.clone())); @@ -127,7 +127,7 @@ impl ValidatorHarness { /// Set the validators slot clock to the specified slot. /// /// The validators slot clock will always read this value until it is set to something else. - pub fn set_slot(&mut self, slot: u64) { - self.slot_clock.set_slot(slot) + pub fn set_slot(&mut self, slot: Slot) { + self.slot_clock.set_slot(slot.as_u64()) } } diff --git a/beacon_node/beacon_chain/test_harness/tests/chain.rs b/beacon_node/beacon_chain/test_harness/tests/chain.rs index c0b537695..8be6f2a26 100644 --- a/beacon_node/beacon_chain/test_harness/tests/chain.rs +++ b/beacon_node/beacon_chain/test_harness/tests/chain.rs @@ -1,13 +1,13 @@ use env_logger::{Builder, Env}; use log::debug; use test_harness::BeaconChainHarness; -use types::ChainSpec; +use types::{ChainSpec, Slot}; #[test] #[ignore] fn it_can_build_on_genesis_block() { let mut spec = ChainSpec::foundation(); - spec.genesis_slot = spec.epoch_length * 8; + spec.genesis_slot = Slot::new(spec.epoch_length * 8); /* spec.shard_count = spec.shard_count / 8; diff --git a/eth2/attester/src/lib.rs b/eth2/attester/src/lib.rs index 4dda24570..7352dd2ea 100644 --- a/eth2/attester/src/lib.rs +++ b/eth2/attester/src/lib.rs @@ -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 { - pub last_processed_slot: Option, + pub last_processed_slot: Option, duties: Arc, slot_clock: Arc, beacon_node: Arc, @@ -91,7 +91,7 @@ impl Attester Result { + fn produce_attestation(&mut self, slot: Slot, shard: u64) -> Result { 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 Attester 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)) diff --git a/eth2/attester/src/test_utils/epoch_map.rs b/eth2/attester/src/test_utils/epoch_map.rs index 88e36c93c..f0dc4312e 100644 --- a/eth2/attester/src/test_utils/epoch_map.rs +++ b/eth2/attester/src/test_utils/epoch_map.rs @@ -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, - map: HashMap, + map: HashMap, } 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, DutiesReaderError> { - let epoch = slot / self.epoch_length; + fn attestation_shard(&self, slot: Slot) -> Result, 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)), diff --git a/eth2/attester/src/test_utils/simulated_beacon_node.rs b/eth2/attester/src/test_utils/simulated_beacon_node.rs index 2f14c9fd3..bab48a975 100644 --- a/eth2/attester/src/test_utils/simulated_beacon_node.rs +++ b/eth2/attester/src/test_utils/simulated_beacon_node.rs @@ -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, BeaconNodeError>; type PublishResult = Result; @@ -8,7 +8,7 @@ type PublishResult = Result; /// A test-only struct used to simulate a Beacon Node. #[derive(Default)] pub struct SimulatedBeaconNode { - pub produce_input: RwLock>, + pub produce_input: RwLock>, pub produce_result: RwLock>, pub publish_input: RwLock>, @@ -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(), diff --git a/eth2/attester/src/traits.rs b/eth2/attester/src/traits.rs index fd07fd171..53bce3aaa 100644 --- a/eth2/attester/src/traits.rs +++ b/eth2/attester/src/traits.rs @@ -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, 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, DutiesReaderError>; + fn attestation_shard(&self, slot: Slot) -> Result, DutiesReaderError>; /// Returns `Some(shard)` if this slot is an attestation slot. Otherwise, returns `None.` fn validator_index(&self) -> Option; diff --git a/eth2/block_producer/src/lib.rs b/eth2/block_producer/src/lib.rs index 8ed10ce1a..0dca583b2 100644 --- a/eth2/block_producer/src/lib.rs +++ b/eth2/block_producer/src/lib.rs @@ -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 { - pub last_processed_slot: Option, + pub last_processed_slot: Option, pubkey: PublicKey, spec: Arc, epoch_map: Arc, @@ -115,7 +115,7 @@ impl BlockProducer 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 BlockProducer Result { + fn produce_block(&mut self, slot: Slot) -> Result { 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))) ); } } diff --git a/eth2/block_producer/src/test_utils/epoch_map.rs b/eth2/block_producer/src/test_utils/epoch_map.rs index c7d1e6b4c..e9ed9b68a 100644 --- a/eth2/block_producer/src/test_utils/epoch_map.rs +++ b/eth2/block_producer/src/test_utils/epoch_map.rs @@ -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, + pub map: HashMap, } impl EpochMap { @@ -16,8 +17,8 @@ impl EpochMap { } impl DutiesReader for EpochMap { - fn is_block_production_slot(&self, slot: u64) -> Result { - let epoch = slot / self.epoch_length; + fn is_block_production_slot(&self, slot: Slot) -> Result { + 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), diff --git a/eth2/block_producer/src/test_utils/simulated_beacon_node.rs b/eth2/block_producer/src/test_utils/simulated_beacon_node.rs index 772670a12..39d03dbe7 100644 --- a/eth2/block_producer/src/test_utils/simulated_beacon_node.rs +++ b/eth2/block_producer/src/test_utils/simulated_beacon_node.rs @@ -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; type ProduceResult = Result, BeaconNodeError>; @@ -12,7 +12,7 @@ pub struct SimulatedBeaconNode { pub nonce_input: RwLock>, pub nonce_result: RwLock>, - pub produce_input: RwLock>, + pub produce_input: RwLock>, pub produce_result: RwLock>, pub publish_input: RwLock>, @@ -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(), diff --git a/eth2/block_producer/src/traits.rs b/eth2/block_producer/src/traits.rs index b09b81e67..5467bee87 100644 --- a/eth2/block_producer/src/traits.rs +++ b/eth2/block_producer/src/traits.rs @@ -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, 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; + fn is_block_production_slot(&self, slot: Slot) -> Result; } /// Signs message using an internally-maintained private key. diff --git a/eth2/naive_fork_choice/src/lib.rs b/eth2/naive_fork_choice/src/lib.rs index 9a7578607..58682fdc6 100644 --- a/eth2/naive_fork_choice/src/lib.rs +++ b/eth2/naive_fork_choice/src/lib.rs @@ -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 = None; + let highest_slot: Option = None; for (_, block) in &head_blocks { let slot = block.slot; diff --git a/eth2/types/Cargo.toml b/eth2/types/Cargo.toml index 77cfb6040..c6550891e 100644 --- a/eth2/types/Cargo.toml +++ b/eth2/types/Cargo.toml @@ -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" } diff --git a/eth2/types/src/slot_epoch.rs b/eth2/types/src/slot_epoch.rs index ccf8ec76d..692c61985 100644 --- a/eth2/types/src/slot_epoch.rs +++ b/eth2/types/src/slot_epoch.rs @@ -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>(&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) + } + } }; } diff --git a/eth2/types/src/spec/foundation.rs b/eth2/types/src/spec/foundation.rs index 46f16ecd9..ea45559a7 100644 --- a/eth2/types/src/spec/foundation.rs +++ b/eth2/types/src/spec/foundation.rs @@ -109,7 +109,7 @@ fn initial_validators_for_testing() -> Vec { 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(), diff --git a/eth2/types/src/validator.rs b/eth2/types/src/validator.rs index 2f535adad..bfbd962b4 100644 --- a/eth2/types/src/validator.rs +++ b/eth2/types/src/validator.rs @@ -46,7 +46,7 @@ fn status_flag_from_byte(flag: u8) -> Result, 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), diff --git a/eth2/utils/slot_clock/Cargo.toml b/eth2/utils/slot_clock/Cargo.toml index 166f397fd..31a435725 100644 --- a/eth2/utils/slot_clock/Cargo.toml +++ b/eth2/utils/slot_clock/Cargo.toml @@ -5,3 +5,4 @@ authors = ["Paul Hauner "] edition = "2018" [dependencies] +types = { path = "../../types" } diff --git a/eth2/utils/slot_clock/src/lib.rs b/eth2/utils/slot_clock/src/lib.rs index 4863f7669..0379d50d9 100644 --- a/eth2/utils/slot_clock/src/lib.rs +++ b/eth2/utils/slot_clock/src/lib.rs @@ -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, Self::Error>; + fn present_slot(&self) -> Result, Self::Error>; } diff --git a/eth2/utils/slot_clock/src/system_time_slot_clock.rs b/eth2/utils/slot_clock/src/system_time_slot_clock.rs index ba62b3b93..99f051985 100644 --- a/eth2/utils/slot_clock/src/system_time_slot_clock.rs +++ b/eth2/utils/slot_clock/src/system_time_slot_clock.rs @@ -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, Error> { + fn present_slot(&self) -> Result, 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 for Error { } } -fn slot_from_duration(slot_duration_seconds: u64, duration: Duration) -> Option { - duration.as_secs().checked_div(slot_duration_seconds) +fn slot_from_duration(slot_duration_seconds: u64, duration: Duration) -> Option { + 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)) ); } diff --git a/eth2/utils/slot_clock/src/testing_slot_clock.rs b/eth2/utils/slot_clock/src/testing_slot_clock.rs index 330d47f1a..80ee40539 100644 --- a/eth2/utils/slot_clock/src/testing_slot_clock.rs +++ b/eth2/utils/slot_clock/src/testing_slot_clock.rs @@ -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, Error> { + fn present_slot(&self) -> Result, 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)))); } } diff --git a/eth2/validator_induction/src/inductor.rs b/eth2/validator_induction/src/inductor.rs index 8dc4c853c..b0a4ba9e6 100644 --- a/eth2/validator_induction/src/inductor.rs +++ b/eth2/validator_induction/src/inductor.rs @@ -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, diff --git a/validator_client/src/block_producer_service/beacon_block_grpc_client.rs b/validator_client/src/block_producer_service/beacon_block_grpc_client.rs index 9ac8e779c..bbf978336 100644 --- a/validator_client/src/block_producer_service/beacon_block_grpc_client.rs +++ b/validator_client/src/block_producer_service/beacon_block_grpc_client.rs @@ -5,7 +5,7 @@ use protos::services::{ use protos::services_grpc::BeaconBlockServiceClient; use ssz::{ssz_encode, Decodable}; use std::sync::Arc; -use types::{BeaconBlock, BeaconBlockBody, Eth1Data, Hash256, PublicKey, Signature}; +use types::{BeaconBlock, BeaconBlockBody, Eth1Data, Hash256, PublicKey, Signature, Slot}; /// A newtype designed to wrap the gRPC-generated service so the `BeaconNode` trait may be /// implemented upon it. @@ -32,11 +32,11 @@ impl BeaconNode for BeaconBlockGrpcClient { /// BN is unable to find a parent block. fn produce_beacon_block( &self, - slot: u64, + slot: Slot, randao_reveal: &Signature, ) -> Result, BeaconNodeError> { let mut req = ProduceBeaconBlockRequest::new(); - req.set_slot(slot); + req.set_slot(slot.as_u64()); let reply = self .client @@ -54,7 +54,7 @@ impl BeaconNode for BeaconBlockGrpcClient { // TODO: this conversion is incomplete; fix it. Ok(Some(BeaconBlock { - slot: block.get_slot(), + slot: Slot::new(block.get_slot()), parent_root: Hash256::zero(), state_root: Hash256::zero(), randao_reveal, @@ -88,7 +88,7 @@ impl BeaconNode for BeaconBlockGrpcClient { // TODO: this conversion is incomplete; fix it. let mut grpc_block = GrpcBeaconBlock::new(); - grpc_block.set_slot(block.slot); + grpc_block.set_slot(block.slot.as_u64()); grpc_block.set_block_root(vec![0]); grpc_block.set_randao_reveal(ssz_encode(&block.randao_reveal)); grpc_block.set_signature(ssz_encode(&block.signature)); diff --git a/validator_client/src/duties/epoch_duties.rs b/validator_client/src/duties/epoch_duties.rs index ea3c8ae4a..d93b8ac2f 100644 --- a/validator_client/src/duties/epoch_duties.rs +++ b/validator_client/src/duties/epoch_duties.rs @@ -1,6 +1,7 @@ use block_producer::{DutiesReader, DutiesReaderError}; use std::collections::HashMap; use std::sync::RwLock; +use types::{Epoch, Slot}; /// The information required for a validator to propose and attest during some epoch. /// @@ -10,14 +11,14 @@ use std::sync::RwLock; #[derive(Debug, PartialEq, Clone, Copy, Default)] pub struct EpochDuties { pub validator_index: u64, - pub block_production_slot: Option, + pub block_production_slot: Option, // Future shard info } impl EpochDuties { /// Returns `true` if the supplied `slot` is a slot in which the validator should produce a /// block. - pub fn is_block_production_slot(&self, slot: u64) -> bool { + pub fn is_block_production_slot(&self, slot: Slot) -> bool { match self.block_production_slot { Some(s) if s == slot => true, _ => false, @@ -32,7 +33,7 @@ pub enum EpochDutiesMapError { /// Maps an `epoch` to some `EpochDuties` for a single validator. pub struct EpochDutiesMap { pub epoch_length: u64, - pub map: RwLock>, + pub map: RwLock>, } impl EpochDutiesMap { @@ -43,7 +44,7 @@ impl EpochDutiesMap { } } - pub fn get(&self, epoch: u64) -> Result, EpochDutiesMapError> { + pub fn get(&self, epoch: Epoch) -> Result, EpochDutiesMapError> { let map = self.map.read().map_err(|_| EpochDutiesMapError::Poisoned)?; match map.get(&epoch) { Some(duties) => Ok(Some(duties.clone())), @@ -53,7 +54,7 @@ impl EpochDutiesMap { pub fn insert( &self, - epoch: u64, + epoch: Epoch, epoch_duties: EpochDuties, ) -> Result, EpochDutiesMapError> { let mut map = self @@ -65,10 +66,8 @@ impl EpochDutiesMap { } impl DutiesReader for EpochDutiesMap { - fn is_block_production_slot(&self, slot: u64) -> Result { - let epoch = slot - .checked_div(self.epoch_length) - .ok_or_else(|| DutiesReaderError::EpochLengthIsZero)?; + fn is_block_production_slot(&self, slot: Slot) -> Result { + let epoch = slot.epoch(self.epoch_length); let map = self.map.read().map_err(|_| DutiesReaderError::Poisoned)?; let duties = map diff --git a/validator_client/src/duties/grpc.rs b/validator_client/src/duties/grpc.rs index b4a2fac51..94f843b63 100644 --- a/validator_client/src/duties/grpc.rs +++ b/validator_client/src/duties/grpc.rs @@ -3,7 +3,7 @@ use super::EpochDuties; use protos::services::{ProposeBlockSlotRequest, PublicKey as IndexRequest}; use protos::services_grpc::ValidatorServiceClient; use ssz::ssz_encode; -use types::PublicKey; +use types::{Epoch, PublicKey, Slot}; impl BeaconNode for ValidatorServiceClient { /// Request the shuffling from the Beacon Node (BN). @@ -14,7 +14,7 @@ impl BeaconNode for ValidatorServiceClient { /// Note: presently only block production information is returned. fn request_shuffling( &self, - epoch: u64, + epoch: Epoch, public_key: &PublicKey, ) -> Result, BeaconNodeError> { // Lookup the validator index for the supplied public key. @@ -29,7 +29,7 @@ impl BeaconNode for ValidatorServiceClient { let mut req = ProposeBlockSlotRequest::new(); req.set_validator_index(validator_index); - req.set_epoch(epoch); + req.set_epoch(epoch.as_u64()); let reply = self .propose_block_slot(&req) @@ -41,6 +41,11 @@ impl BeaconNode for ValidatorServiceClient { None }; + let block_production_slot = match block_production_slot { + Some(slot) => Some(Slot::new(slot)), + None => None, + }; + Ok(Some(EpochDuties { validator_index, block_production_slot, diff --git a/validator_client/src/duties/mod.rs b/validator_client/src/duties/mod.rs index 711a1e29c..936034aca 100644 --- a/validator_client/src/duties/mod.rs +++ b/validator_client/src/duties/mod.rs @@ -12,20 +12,20 @@ use self::traits::{BeaconNode, BeaconNodeError}; use bls::PublicKey; use slot_clock::SlotClock; use std::sync::Arc; -use types::ChainSpec; +use types::{ChainSpec, Epoch, Slot}; #[derive(Debug, PartialEq, Clone, Copy)] pub enum PollOutcome { /// The `EpochDuties` were not updated during this poll. - NoChange(u64), + NoChange(Epoch), /// The `EpochDuties` for the `epoch` were previously unknown, but obtained in the poll. - NewDuties(u64, EpochDuties), + NewDuties(Epoch, EpochDuties), /// New `EpochDuties` were obtained, different to those which were previously known. This is /// likely to be the result of chain re-organisation. - DutiesChanged(u64, EpochDuties), + DutiesChanged(Epoch, EpochDuties), /// The Beacon Node was unable to return the duties as the validator is unknown, or the /// shuffling for the epoch is unknown. - UnknownValidatorOrEpoch(u64), + UnknownValidatorOrEpoch(Epoch), } #[derive(Debug, PartialEq)] @@ -62,9 +62,7 @@ impl DutiesManager { .map_err(|_| Error::SlotClockError)? .ok_or(Error::SlotUnknowable)?; - let epoch = slot - .checked_div(self.spec.epoch_length) - .ok_or(Error::EpochLengthIsZero)?; + let epoch = slot.epoch(self.spec.epoch_length); if let Some(duties) = self.beacon_node.request_shuffling(epoch, &self.pubkey)? { // If these duties were known, check to see if they're updates or identical. @@ -130,25 +128,34 @@ mod tests { // Configure response from the BeaconNode. let duties = EpochDuties { validator_index: 0, - block_production_slot: Some(10), + block_production_slot: Some(Slot::new(10)), }; beacon_node.set_next_shuffling_result(Ok(Some(duties))); // Get the duties for the first time... - assert_eq!(manager.poll(), Ok(PollOutcome::NewDuties(0, duties))); + assert_eq!( + manager.poll(), + Ok(PollOutcome::NewDuties(Epoch::new(0), duties)) + ); // Get the same duties again... - assert_eq!(manager.poll(), Ok(PollOutcome::NoChange(0))); + assert_eq!(manager.poll(), Ok(PollOutcome::NoChange(Epoch::new(0)))); // Return new duties. let duties = EpochDuties { validator_index: 0, - block_production_slot: Some(11), + block_production_slot: Some(Slot::new(11)), }; beacon_node.set_next_shuffling_result(Ok(Some(duties))); - assert_eq!(manager.poll(), Ok(PollOutcome::DutiesChanged(0, duties))); + assert_eq!( + manager.poll(), + Ok(PollOutcome::DutiesChanged(Epoch::new(0), duties)) + ); // Return no duties. beacon_node.set_next_shuffling_result(Ok(None)); - assert_eq!(manager.poll(), Ok(PollOutcome::UnknownValidatorOrEpoch(0))); + assert_eq!( + manager.poll(), + Ok(PollOutcome::UnknownValidatorOrEpoch(Epoch::new(0))) + ); } } diff --git a/validator_client/src/duties/test_node.rs b/validator_client/src/duties/test_node.rs index 2b1d65172..331b78f3b 100644 --- a/validator_client/src/duties/test_node.rs +++ b/validator_client/src/duties/test_node.rs @@ -2,13 +2,14 @@ use super::traits::{BeaconNode, BeaconNodeError}; use super::EpochDuties; use bls::PublicKey; use std::sync::RwLock; +use types::Epoch; type ShufflingResult = Result, BeaconNodeError>; /// A test-only struct used to simulate a Beacon Node. #[derive(Default)] pub struct TestBeaconNode { - pub request_shuffling_input: RwLock>, + pub request_shuffling_input: RwLock>, pub request_shuffling_result: RwLock>, } @@ -21,7 +22,7 @@ impl TestBeaconNode { impl BeaconNode for TestBeaconNode { /// Returns the value specified by the `set_next_shuffling_result`. - fn request_shuffling(&self, epoch: u64, public_key: &PublicKey) -> ShufflingResult { + fn request_shuffling(&self, epoch: Epoch, public_key: &PublicKey) -> ShufflingResult { *self.request_shuffling_input.write().unwrap() = Some((epoch, public_key.clone())); match *self.request_shuffling_result.read().unwrap() { Some(ref r) => r.clone(), diff --git a/validator_client/src/duties/traits.rs b/validator_client/src/duties/traits.rs index 38d61f967..5bf7da1fd 100644 --- a/validator_client/src/duties/traits.rs +++ b/validator_client/src/duties/traits.rs @@ -1,5 +1,6 @@ use super::EpochDuties; use bls::PublicKey; +use types::Epoch; #[derive(Debug, PartialEq, Clone)] pub enum BeaconNodeError { @@ -13,7 +14,7 @@ pub trait BeaconNode: Send + Sync { /// Returns Ok(None) if the public key is unknown, or the shuffling for that epoch is unknown. fn request_shuffling( &self, - epoch: u64, + epoch: Epoch, public_key: &PublicKey, ) -> Result, BeaconNodeError>; }