Fix all compile errors from new Slot/Epoch types
This commit is contained in:
parent
9b1d8cd3c1
commit
85450ec254
@ -230,7 +230,7 @@ where
|
|||||||
/// Returns `None` if the `validator_index` is invalid.
|
/// Returns `None` if the `validator_index` is invalid.
|
||||||
///
|
///
|
||||||
/// Information is retrieved from the present `beacon_state.validator_registry`.
|
/// Information is retrieved from the present `beacon_state.validator_registry`.
|
||||||
pub fn proposer_slots(&self, validator_index: usize) -> Option<Slot> {
|
pub fn proposer_slots(&self, validator_index: usize) -> Option<u64> {
|
||||||
if let Some(validator) = self.state.read().validator_registry.get(validator_index) {
|
if let Some(validator) = self.state.read().validator_registry.get(validator_index) {
|
||||||
Some(validator.proposer_slots)
|
Some(validator.proposer_slots)
|
||||||
} else {
|
} else {
|
||||||
@ -248,7 +248,7 @@ where
|
|||||||
/// `self.state` should undergo per slot processing.
|
/// `self.state` should undergo per slot processing.
|
||||||
pub fn read_slot_clock(&self) -> Option<Slot> {
|
pub fn read_slot_clock(&self) -> Option<Slot> {
|
||||||
match self.slot_clock.present_slot() {
|
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,
|
Ok(None) => None,
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ use std::fs::File;
|
|||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::sync::Arc;
|
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
|
/// 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
|
/// 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 block_store = Arc::new(BeaconBlockStore::new(db.clone()));
|
||||||
let state_store = Arc::new(BeaconStateStore::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).
|
// Remove the validators present in the spec (if any).
|
||||||
spec.initial_validators = Vec::with_capacity(validator_count);
|
spec.initial_validators = Vec::with_capacity(validator_count);
|
||||||
@ -60,7 +60,7 @@ impl BeaconChainHarness {
|
|||||||
.par_iter()
|
.par_iter()
|
||||||
.map(|keypair| Validator {
|
.map(|keypair| Validator {
|
||||||
pubkey: keypair.pk.clone(),
|
pubkey: keypair.pk.clone(),
|
||||||
activation_slot: 0,
|
activation_slot: Slot::new(0),
|
||||||
..std::default::Default::default()
|
..std::default::Default::default()
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@ -115,12 +115,12 @@ impl BeaconChainHarness {
|
|||||||
/// This is the equivalent of advancing a system clock forward one `SLOT_DURATION`.
|
/// This is the equivalent of advancing a system clock forward one `SLOT_DURATION`.
|
||||||
///
|
///
|
||||||
/// Returns the new slot.
|
/// 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;
|
let slot = self.beacon_chain.present_slot() + 1;
|
||||||
|
|
||||||
debug!("Incrementing BeaconChain slot to {}.", slot);
|
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();
|
self.beacon_chain.advance_state(slot).unwrap();
|
||||||
slot
|
slot
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ use db::ClientDB;
|
|||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::{AttestationData, BeaconBlock, FreeAttestation, PublicKey, Signature};
|
use types::{AttestationData, BeaconBlock, FreeAttestation, PublicKey, Signature, Slot};
|
||||||
|
|
||||||
// mod attester;
|
// mod attester;
|
||||||
// mod producer;
|
// mod producer;
|
||||||
@ -51,7 +51,7 @@ impl<T: ClientDB, U: SlotClock> DirectBeaconNode<T, U> {
|
|||||||
impl<T: ClientDB, U: SlotClock> AttesterBeaconNode for DirectBeaconNode<T, U> {
|
impl<T: ClientDB, U: SlotClock> AttesterBeaconNode for DirectBeaconNode<T, U> {
|
||||||
fn produce_attestation_data(
|
fn produce_attestation_data(
|
||||||
&self,
|
&self,
|
||||||
_slot: u64,
|
_slot: Slot,
|
||||||
shard: u64,
|
shard: u64,
|
||||||
) -> Result<Option<AttestationData>, NodeError> {
|
) -> Result<Option<AttestationData>, NodeError> {
|
||||||
match self.beacon_chain.produce_attestation_data(shard) {
|
match self.beacon_chain.produce_attestation_data(shard) {
|
||||||
@ -87,7 +87,7 @@ impl<T: ClientDB, U: SlotClock> BeaconBlockNode for DirectBeaconNode<T, U> {
|
|||||||
/// Requests a new `BeaconBlock from the `BeaconChain`.
|
/// Requests a new `BeaconBlock from the `BeaconChain`.
|
||||||
fn produce_beacon_block(
|
fn produce_beacon_block(
|
||||||
&self,
|
&self,
|
||||||
slot: u64,
|
slot: Slot,
|
||||||
randao_reveal: &Signature,
|
randao_reveal: &Signature,
|
||||||
) -> Result<Option<BeaconBlock>, BeaconBlockNodeError> {
|
) -> Result<Option<BeaconBlock>, BeaconBlockNodeError> {
|
||||||
let (block, _state) = self
|
let (block, _state) = self
|
||||||
|
@ -8,7 +8,7 @@ use block_producer::{
|
|||||||
use db::ClientDB;
|
use db::ClientDB;
|
||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::PublicKey;
|
use types::{PublicKey, Slot};
|
||||||
|
|
||||||
/// Connects directly to a borrowed `BeaconChain` and reads attester/proposer duties directly from
|
/// Connects directly to a borrowed `BeaconChain` and reads attester/proposer duties directly from
|
||||||
/// it.
|
/// it.
|
||||||
@ -27,7 +27,7 @@ impl<T: ClientDB, U: SlotClock> DirectDuties<T, U> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ClientDB, U: SlotClock> ProducerDutiesReader for DirectDuties<T, U> {
|
impl<T: ClientDB, U: SlotClock> ProducerDutiesReader for DirectDuties<T, U> {
|
||||||
fn is_block_production_slot(&self, slot: u64) -> Result<bool, ProducerDutiesReaderError> {
|
fn is_block_production_slot(&self, slot: Slot) -> Result<bool, ProducerDutiesReaderError> {
|
||||||
let validator_index = self
|
let validator_index = self
|
||||||
.beacon_chain
|
.beacon_chain
|
||||||
.validator_index(&self.pubkey)
|
.validator_index(&self.pubkey)
|
||||||
@ -49,7 +49,7 @@ impl<T: ClientDB, U: SlotClock> AttesterDutiesReader for DirectDuties<T, U> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attestation_shard(&self, slot: u64) -> Result<Option<u64>, AttesterDutiesReaderError> {
|
fn attestation_shard(&self, slot: Slot) -> Result<Option<u64>, AttesterDutiesReaderError> {
|
||||||
if let Some(validator_index) = self.validator_index() {
|
if let Some(validator_index) = self.validator_index() {
|
||||||
match self
|
match self
|
||||||
.beacon_chain
|
.beacon_chain
|
||||||
|
@ -9,7 +9,7 @@ use block_producer::{BlockProducer, Error as BlockPollError};
|
|||||||
use db::MemoryDB;
|
use db::MemoryDB;
|
||||||
use slot_clock::TestingSlotClock;
|
use slot_clock::TestingSlotClock;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::{BeaconBlock, ChainSpec, FreeAttestation, Keypair};
|
use types::{BeaconBlock, ChainSpec, FreeAttestation, Keypair, Slot};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum BlockProduceError {
|
pub enum BlockProduceError {
|
||||||
@ -59,7 +59,7 @@ impl ValidatorHarness {
|
|||||||
beacon_chain: Arc<BeaconChain<MemoryDB, TestingSlotClock>>,
|
beacon_chain: Arc<BeaconChain<MemoryDB, TestingSlotClock>>,
|
||||||
spec: Arc<ChainSpec>,
|
spec: Arc<ChainSpec>,
|
||||||
) -> Self {
|
) -> 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 signer = Arc::new(LocalSigner::new(keypair.clone()));
|
||||||
let beacon_node = Arc::new(DirectBeaconNode::new(beacon_chain.clone()));
|
let beacon_node = Arc::new(DirectBeaconNode::new(beacon_chain.clone()));
|
||||||
let epoch_map = Arc::new(DirectDuties::new(keypair.pk.clone(), 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.
|
/// 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.
|
/// The validators slot clock will always read this value until it is set to something else.
|
||||||
pub fn set_slot(&mut self, slot: u64) {
|
pub fn set_slot(&mut self, slot: Slot) {
|
||||||
self.slot_clock.set_slot(slot)
|
self.slot_clock.set_slot(slot.as_u64())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use env_logger::{Builder, Env};
|
use env_logger::{Builder, Env};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use test_harness::BeaconChainHarness;
|
use test_harness::BeaconChainHarness;
|
||||||
use types::ChainSpec;
|
use types::{ChainSpec, Slot};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn it_can_build_on_genesis_block() {
|
fn it_can_build_on_genesis_block() {
|
||||||
let mut spec = ChainSpec::foundation();
|
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;
|
spec.shard_count = spec.shard_count / 8;
|
||||||
|
@ -3,7 +3,7 @@ mod traits;
|
|||||||
|
|
||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::{AttestationData, FreeAttestation, Signature};
|
use types::{AttestationData, FreeAttestation, Signature, Slot};
|
||||||
|
|
||||||
pub use self::traits::{
|
pub use self::traits::{
|
||||||
BeaconNode, BeaconNodeError, DutiesReader, DutiesReaderError, PublishOutcome, Signer,
|
BeaconNode, BeaconNodeError, DutiesReader, DutiesReaderError, PublishOutcome, Signer,
|
||||||
@ -13,14 +13,14 @@ const PHASE_0_CUSTODY_BIT: bool = false;
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum PollOutcome {
|
pub enum PollOutcome {
|
||||||
AttestationProduced(u64),
|
AttestationProduced(Slot),
|
||||||
AttestationNotRequired(u64),
|
AttestationNotRequired(Slot),
|
||||||
SlashableAttestationNotProduced(u64),
|
SlashableAttestationNotProduced(Slot),
|
||||||
BeaconNodeUnableToProduceAttestation(u64),
|
BeaconNodeUnableToProduceAttestation(Slot),
|
||||||
ProducerDutiesUnknown(u64),
|
ProducerDutiesUnknown(Slot),
|
||||||
SlotAlreadyProcessed(u64),
|
SlotAlreadyProcessed(Slot),
|
||||||
SignerRejection(u64),
|
SignerRejection(Slot),
|
||||||
ValidatorIsUnknown(u64),
|
ValidatorIsUnknown(Slot),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
@ -40,7 +40,7 @@ pub enum Error {
|
|||||||
///
|
///
|
||||||
/// Relies upon an external service to keep the `EpochDutiesMap` updated.
|
/// Relies upon an external service to keep the `EpochDutiesMap` updated.
|
||||||
pub struct Attester<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> {
|
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>,
|
duties: Arc<V>,
|
||||||
slot_clock: Arc<T>,
|
slot_clock: Arc<T>,
|
||||||
beacon_node: Arc<U>,
|
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)? {
|
let attestation_data = match self.beacon_node.produce_attestation_data(slot, shard)? {
|
||||||
Some(attestation_data) => attestation_data,
|
Some(attestation_data) => attestation_data,
|
||||||
None => return Ok(PollOutcome::BeaconNodeUnableToProduceAttestation(slot)),
|
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))
|
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 {
|
match self.last_processed_slot {
|
||||||
Some(processed_slot) if slot <= processed_slot => true,
|
Some(processed_slot) if slot <= processed_slot => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
@ -193,7 +193,7 @@ mod tests {
|
|||||||
let signer = Arc::new(LocalSigner::new(Keypair::random()));
|
let signer = Arc::new(LocalSigner::new(Keypair::random()));
|
||||||
|
|
||||||
let mut duties = EpochMap::new(spec.epoch_length);
|
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_epoch = attest_slot / spec.epoch_length;
|
||||||
let attest_shard = 12;
|
let attest_shard = 12;
|
||||||
duties.insert_attestation_shard(attest_slot, attest_shard);
|
duties.insert_attestation_shard(attest_slot, attest_shard);
|
||||||
@ -212,28 +212,28 @@ mod tests {
|
|||||||
beacon_node.set_next_publish_result(Ok(PublishOutcome::ValidAttestation));
|
beacon_node.set_next_publish_result(Ok(PublishOutcome::ValidAttestation));
|
||||||
|
|
||||||
// One slot before attestation slot...
|
// One slot before attestation slot...
|
||||||
slot_clock.set_slot(attest_slot - 1);
|
slot_clock.set_slot(attest_slot.as_u64() - 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
attester.poll(),
|
attester.poll(),
|
||||||
Ok(PollOutcome::AttestationNotRequired(attest_slot - 1))
|
Ok(PollOutcome::AttestationNotRequired(attest_slot - 1))
|
||||||
);
|
);
|
||||||
|
|
||||||
// On the attest slot...
|
// On the attest slot...
|
||||||
slot_clock.set_slot(attest_slot);
|
slot_clock.set_slot(attest_slot.as_u64());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
attester.poll(),
|
attester.poll(),
|
||||||
Ok(PollOutcome::AttestationProduced(attest_slot))
|
Ok(PollOutcome::AttestationProduced(attest_slot))
|
||||||
);
|
);
|
||||||
|
|
||||||
// Trying the same attest slot again...
|
// Trying the same attest slot again...
|
||||||
slot_clock.set_slot(attest_slot);
|
slot_clock.set_slot(attest_slot.as_u64());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
attester.poll(),
|
attester.poll(),
|
||||||
Ok(PollOutcome::SlotAlreadyProcessed(attest_slot))
|
Ok(PollOutcome::SlotAlreadyProcessed(attest_slot))
|
||||||
);
|
);
|
||||||
|
|
||||||
// One slot after the 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!(
|
assert_eq!(
|
||||||
attester.poll(),
|
attester.poll(),
|
||||||
Ok(PollOutcome::AttestationNotRequired(attest_slot + 1))
|
Ok(PollOutcome::AttestationNotRequired(attest_slot + 1))
|
||||||
@ -241,7 +241,7 @@ mod tests {
|
|||||||
|
|
||||||
// In an epoch without known duties...
|
// In an epoch without known duties...
|
||||||
let slot = (attest_epoch + 1) * spec.epoch_length;
|
let slot = (attest_epoch + 1) * spec.epoch_length;
|
||||||
slot_clock.set_slot(slot);
|
slot_clock.set_slot(slot.into());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
attester.poll(),
|
attester.poll(),
|
||||||
Ok(PollOutcome::ProducerDutiesUnknown(slot))
|
Ok(PollOutcome::ProducerDutiesUnknown(slot))
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
use crate::{DutiesReader, DutiesReaderError};
|
use crate::{DutiesReader, DutiesReaderError};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use types::{Epoch, Slot};
|
||||||
|
|
||||||
pub struct EpochMap {
|
pub struct EpochMap {
|
||||||
epoch_length: u64,
|
epoch_length: u64,
|
||||||
validator_index: Option<u64>,
|
validator_index: Option<u64>,
|
||||||
map: HashMap<u64, (u64, u64)>,
|
map: HashMap<Epoch, (Slot, u64)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EpochMap {
|
impl EpochMap {
|
||||||
@ -16,9 +17,8 @@ impl EpochMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_attestation_shard(&mut self, slot: u64, shard: u64) {
|
pub fn insert_attestation_shard(&mut self, slot: Slot, shard: u64) {
|
||||||
let epoch = slot / self.epoch_length;
|
let epoch = slot.epoch(self.epoch_length);
|
||||||
|
|
||||||
self.map.insert(epoch, (slot, shard));
|
self.map.insert(epoch, (slot, shard));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,8 +28,8 @@ impl EpochMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DutiesReader for EpochMap {
|
impl DutiesReader for EpochMap {
|
||||||
fn attestation_shard(&self, slot: u64) -> Result<Option<u64>, DutiesReaderError> {
|
fn attestation_shard(&self, slot: Slot) -> Result<Option<u64>, DutiesReaderError> {
|
||||||
let epoch = slot / self.epoch_length;
|
let epoch = slot.epoch(self.epoch_length);
|
||||||
|
|
||||||
match self.map.get(&epoch) {
|
match self.map.get(&epoch) {
|
||||||
Some((attest_slot, attest_shard)) if *attest_slot == slot => Ok(Some(*attest_shard)),
|
Some((attest_slot, attest_shard)) if *attest_slot == slot => Ok(Some(*attest_shard)),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::traits::{BeaconNode, BeaconNodeError, PublishOutcome};
|
use crate::traits::{BeaconNode, BeaconNodeError, PublishOutcome};
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
use types::{AttestationData, FreeAttestation};
|
use types::{AttestationData, FreeAttestation, Slot};
|
||||||
|
|
||||||
type ProduceResult = Result<Option<AttestationData>, BeaconNodeError>;
|
type ProduceResult = Result<Option<AttestationData>, BeaconNodeError>;
|
||||||
type PublishResult = Result<PublishOutcome, 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.
|
/// A test-only struct used to simulate a Beacon Node.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct SimulatedBeaconNode {
|
pub struct SimulatedBeaconNode {
|
||||||
pub produce_input: RwLock<Option<(u64, u64)>>,
|
pub produce_input: RwLock<Option<(Slot, u64)>>,
|
||||||
pub produce_result: RwLock<Option<ProduceResult>>,
|
pub produce_result: RwLock<Option<ProduceResult>>,
|
||||||
|
|
||||||
pub publish_input: RwLock<Option<FreeAttestation>>,
|
pub publish_input: RwLock<Option<FreeAttestation>>,
|
||||||
@ -26,7 +26,7 @@ impl SimulatedBeaconNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BeaconNode for 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));
|
*self.produce_input.write().unwrap() = Some((slot, shard));
|
||||||
match *self.produce_result.read().unwrap() {
|
match *self.produce_result.read().unwrap() {
|
||||||
Some(ref r) => r.clone(),
|
Some(ref r) => r.clone(),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use types::{AttestationData, FreeAttestation, Signature};
|
use types::{AttestationData, FreeAttestation, Signature, Slot};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum BeaconNodeError {
|
pub enum BeaconNodeError {
|
||||||
@ -16,7 +16,7 @@ pub enum PublishOutcome {
|
|||||||
pub trait BeaconNode: Send + Sync {
|
pub trait BeaconNode: Send + Sync {
|
||||||
fn produce_attestation_data(
|
fn produce_attestation_data(
|
||||||
&self,
|
&self,
|
||||||
slot: u64,
|
slot: Slot,
|
||||||
shard: u64,
|
shard: u64,
|
||||||
) -> Result<Option<AttestationData>, BeaconNodeError>;
|
) -> Result<Option<AttestationData>, BeaconNodeError>;
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ pub enum DutiesReaderError {
|
|||||||
/// Informs a validator of their duties (e.g., block production).
|
/// Informs a validator of their duties (e.g., block production).
|
||||||
pub trait DutiesReader: Send + Sync {
|
pub trait DutiesReader: Send + Sync {
|
||||||
/// Returns `Some(shard)` if this slot is an attestation slot. Otherwise, returns `None.`
|
/// 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.`
|
/// Returns `Some(shard)` if this slot is an attestation slot. Otherwise, returns `None.`
|
||||||
fn validator_index(&self) -> Option<u64>;
|
fn validator_index(&self) -> Option<u64>;
|
||||||
|
@ -4,7 +4,7 @@ mod traits;
|
|||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
use ssz::ssz_encode;
|
use ssz::ssz_encode;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::{BeaconBlock, ChainSpec, PublicKey};
|
use types::{BeaconBlock, ChainSpec, PublicKey, Slot};
|
||||||
|
|
||||||
pub use self::traits::{
|
pub use self::traits::{
|
||||||
BeaconNode, BeaconNodeError, DutiesReader, DutiesReaderError, PublishOutcome, Signer,
|
BeaconNode, BeaconNodeError, DutiesReader, DutiesReaderError, PublishOutcome, Signer,
|
||||||
@ -13,21 +13,21 @@ pub use self::traits::{
|
|||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum PollOutcome {
|
pub enum PollOutcome {
|
||||||
/// A new block was produced.
|
/// A new block was produced.
|
||||||
BlockProduced(u64),
|
BlockProduced(Slot),
|
||||||
/// A block was not produced as it would have been slashable.
|
/// 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.
|
/// The validator duties did not require a block to be produced.
|
||||||
BlockProductionNotRequired(u64),
|
BlockProductionNotRequired(Slot),
|
||||||
/// The duties for the present epoch were not found.
|
/// The duties for the present epoch were not found.
|
||||||
ProducerDutiesUnknown(u64),
|
ProducerDutiesUnknown(Slot),
|
||||||
/// The slot has already been processed, execution was skipped.
|
/// 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.
|
/// The Beacon Node was unable to produce a block at that slot.
|
||||||
BeaconNodeUnableToProduceBlock(u64),
|
BeaconNodeUnableToProduceBlock(Slot),
|
||||||
/// The signer failed to sign the message.
|
/// The signer failed to sign the message.
|
||||||
SignerRejection(u64),
|
SignerRejection(Slot),
|
||||||
/// The public key for this validator is not an active validator.
|
/// The public key for this validator is not an active validator.
|
||||||
ValidatorIsUnknown(u64),
|
ValidatorIsUnknown(Slot),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
@ -47,7 +47,7 @@ pub enum Error {
|
|||||||
///
|
///
|
||||||
/// Relies upon an external service to keep the `EpochDutiesMap` updated.
|
/// Relies upon an external service to keep the `EpochDutiesMap` updated.
|
||||||
pub struct BlockProducer<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> {
|
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,
|
pubkey: PublicKey,
|
||||||
spec: Arc<ChainSpec>,
|
spec: Arc<ChainSpec>,
|
||||||
epoch_map: Arc<V>,
|
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 {
|
match self.last_processed_slot {
|
||||||
Some(processed_slot) if processed_slot >= slot => true,
|
Some(processed_slot) if processed_slot >= slot => true,
|
||||||
_ => false,
|
_ => 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
|
/// The slash-protection code is not yet implemented. There is zero protection against
|
||||||
/// slashing.
|
/// 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 randao_reveal = {
|
||||||
let producer_nonce = self.beacon_node.proposer_nonce(&self.pubkey)?;
|
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 signer = Arc::new(LocalSigner::new(Keypair::random()));
|
||||||
|
|
||||||
let mut epoch_map = EpochMap::new(spec.epoch_length);
|
let mut epoch_map = EpochMap::new(spec.epoch_length);
|
||||||
let produce_slot = 100;
|
let produce_slot = Slot::new(100);
|
||||||
let produce_epoch = produce_slot / spec.epoch_length;
|
let produce_epoch = produce_slot.epoch(spec.epoch_length);
|
||||||
epoch_map.map.insert(produce_epoch, produce_slot);
|
epoch_map.map.insert(produce_epoch, produce_slot);
|
||||||
let epoch_map = Arc::new(epoch_map);
|
let epoch_map = Arc::new(epoch_map);
|
||||||
let keypair = Keypair::random();
|
let keypair = Keypair::random();
|
||||||
@ -257,39 +257,39 @@ mod tests {
|
|||||||
beacon_node.set_next_nonce_result(Ok(0));
|
beacon_node.set_next_nonce_result(Ok(0));
|
||||||
|
|
||||||
// One slot before production slot...
|
// One slot before production slot...
|
||||||
slot_clock.set_slot(produce_slot - 1);
|
slot_clock.set_slot(produce_slot.as_u64() - 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
block_producer.poll(),
|
block_producer.poll(),
|
||||||
Ok(PollOutcome::BlockProductionNotRequired(produce_slot - 1))
|
Ok(PollOutcome::BlockProductionNotRequired(produce_slot - 1))
|
||||||
);
|
);
|
||||||
|
|
||||||
// On the produce slot...
|
// On the produce slot...
|
||||||
slot_clock.set_slot(produce_slot);
|
slot_clock.set_slot(produce_slot.as_u64());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
block_producer.poll(),
|
block_producer.poll(),
|
||||||
Ok(PollOutcome::BlockProduced(produce_slot))
|
Ok(PollOutcome::BlockProduced(produce_slot.into()))
|
||||||
);
|
);
|
||||||
|
|
||||||
// Trying the same produce slot again...
|
// Trying the same produce slot again...
|
||||||
slot_clock.set_slot(produce_slot);
|
slot_clock.set_slot(produce_slot.as_u64());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
block_producer.poll(),
|
block_producer.poll(),
|
||||||
Ok(PollOutcome::SlotAlreadyProcessed(produce_slot))
|
Ok(PollOutcome::SlotAlreadyProcessed(produce_slot))
|
||||||
);
|
);
|
||||||
|
|
||||||
// One slot after the 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!(
|
assert_eq!(
|
||||||
block_producer.poll(),
|
block_producer.poll(),
|
||||||
Ok(PollOutcome::BlockProductionNotRequired(produce_slot + 1))
|
Ok(PollOutcome::BlockProductionNotRequired(produce_slot + 1))
|
||||||
);
|
);
|
||||||
|
|
||||||
// In an epoch without known duties...
|
// 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);
|
slot_clock.set_slot(slot);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
block_producer.poll(),
|
block_producer.poll(),
|
||||||
Ok(PollOutcome::ProducerDutiesUnknown(slot))
|
Ok(PollOutcome::ProducerDutiesUnknown(Slot::new(slot)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
use crate::{DutiesReader, DutiesReaderError};
|
use crate::{DutiesReader, DutiesReaderError};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use types::{Epoch, Slot};
|
||||||
|
|
||||||
pub struct EpochMap {
|
pub struct EpochMap {
|
||||||
epoch_length: u64,
|
epoch_length: u64,
|
||||||
pub map: HashMap<u64, u64>,
|
pub map: HashMap<Epoch, Slot>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EpochMap {
|
impl EpochMap {
|
||||||
@ -16,8 +17,8 @@ impl EpochMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DutiesReader for EpochMap {
|
impl DutiesReader for EpochMap {
|
||||||
fn is_block_production_slot(&self, slot: u64) -> Result<bool, DutiesReaderError> {
|
fn is_block_production_slot(&self, slot: Slot) -> Result<bool, DutiesReaderError> {
|
||||||
let epoch = slot / self.epoch_length;
|
let epoch = slot.epoch(self.epoch_length);
|
||||||
match self.map.get(&epoch) {
|
match self.map.get(&epoch) {
|
||||||
Some(s) if *s == slot => Ok(true),
|
Some(s) if *s == slot => Ok(true),
|
||||||
Some(s) if *s != slot => Ok(false),
|
Some(s) if *s != slot => Ok(false),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::traits::{BeaconNode, BeaconNodeError, PublishOutcome};
|
use crate::traits::{BeaconNode, BeaconNodeError, PublishOutcome};
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
use types::{BeaconBlock, PublicKey, Signature};
|
use types::{BeaconBlock, PublicKey, Signature, Slot};
|
||||||
|
|
||||||
type NonceResult = Result<u64, BeaconNodeError>;
|
type NonceResult = Result<u64, BeaconNodeError>;
|
||||||
type ProduceResult = Result<Option<BeaconBlock>, BeaconNodeError>;
|
type ProduceResult = Result<Option<BeaconBlock>, BeaconNodeError>;
|
||||||
@ -12,7 +12,7 @@ pub struct SimulatedBeaconNode {
|
|||||||
pub nonce_input: RwLock<Option<PublicKey>>,
|
pub nonce_input: RwLock<Option<PublicKey>>,
|
||||||
pub nonce_result: RwLock<Option<NonceResult>>,
|
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 produce_result: RwLock<Option<ProduceResult>>,
|
||||||
|
|
||||||
pub publish_input: RwLock<Option<BeaconBlock>>,
|
pub publish_input: RwLock<Option<BeaconBlock>>,
|
||||||
@ -46,7 +46,7 @@ impl BeaconNode for SimulatedBeaconNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the value specified by the `set_next_produce_result`.
|
/// 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()));
|
*self.produce_input.write().unwrap() = Some((slot, randao_reveal.clone()));
|
||||||
match *self.produce_result.read().unwrap() {
|
match *self.produce_result.read().unwrap() {
|
||||||
Some(ref r) => r.clone(),
|
Some(ref r) => r.clone(),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use types::{BeaconBlock, PublicKey, Signature};
|
use types::{BeaconBlock, PublicKey, Signature, Slot};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum BeaconNodeError {
|
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.
|
/// Returns Ok(None) if the Beacon Node is unable to produce at the given slot.
|
||||||
fn produce_beacon_block(
|
fn produce_beacon_block(
|
||||||
&self,
|
&self,
|
||||||
slot: u64,
|
slot: Slot,
|
||||||
randao_reveal: &Signature,
|
randao_reveal: &Signature,
|
||||||
) -> Result<Option<BeaconBlock>, BeaconNodeError>;
|
) -> Result<Option<BeaconBlock>, BeaconNodeError>;
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ pub enum DutiesReaderError {
|
|||||||
|
|
||||||
/// Informs a validator of their duties (e.g., block production).
|
/// Informs a validator of their duties (e.g., block production).
|
||||||
pub trait DutiesReader: Send + Sync {
|
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.
|
/// Signs message using an internally-maintained private key.
|
||||||
|
@ -6,7 +6,7 @@ use db::stores::BeaconBlockStore;
|
|||||||
use db::{ClientDB, DBError};
|
use db::{ClientDB, DBError};
|
||||||
use ssz::{Decodable, DecodeError};
|
use ssz::{Decodable, DecodeError};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::{BeaconBlock, Hash256};
|
use types::{BeaconBlock, Hash256, Slot};
|
||||||
|
|
||||||
pub enum ForkChoiceError {
|
pub enum ForkChoiceError {
|
||||||
BadSszInDatabase,
|
BadSszInDatabase,
|
||||||
@ -37,7 +37,7 @@ where
|
|||||||
/*
|
/*
|
||||||
* Loop through all the head blocks and find the highest slot.
|
* 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 {
|
for (_, block) in &head_blocks {
|
||||||
let slot = block.slot;
|
let slot = block.slot;
|
||||||
|
|
||||||
|
@ -17,5 +17,6 @@ rand = "0.5.5"
|
|||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
slog = "^2.2.3"
|
||||||
ssz = { path = "../utils/ssz" }
|
ssz = { path = "../utils/ssz" }
|
||||||
vec_shuffle = { path = "../utils/vec_shuffle" }
|
vec_shuffle = { path = "../utils/vec_shuffle" }
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use serde_derive::Serialize;
|
use serde_derive::Serialize;
|
||||||
|
use slog;
|
||||||
use ssz::{hash, Decodable, DecodeError, Encodable, SszStream, TreeHash};
|
use ssz::{hash, Decodable, DecodeError, Encodable, SszStream, TreeHash};
|
||||||
use std::cmp::{Ord, Ordering};
|
use std::cmp::{Ord, Ordering};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@ -162,6 +163,15 @@ macro_rules! impl_math {
|
|||||||
*self - other.into()
|
*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 {
|
pub fn is_power_of_two(&self) -> bool {
|
||||||
self.0.is_power_of_two()
|
self.0.is_power_of_two()
|
||||||
}
|
}
|
||||||
@ -183,6 +193,17 @@ macro_rules! impl_display {
|
|||||||
write!(f, "{}", self.0)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ fn initial_validators_for_testing() -> Vec<Validator> {
|
|||||||
let validator = Validator {
|
let validator = Validator {
|
||||||
pubkey: keypair.pk.clone(),
|
pubkey: keypair.pk.clone(),
|
||||||
withdrawal_credentials: Hash256::zero(),
|
withdrawal_credentials: Hash256::zero(),
|
||||||
proposer_slots: Slot::from(0_u64),
|
proposer_slots: 0,
|
||||||
activation_slot: Slot::max_value(),
|
activation_slot: Slot::max_value(),
|
||||||
exit_slot: Slot::max_value(),
|
exit_slot: Slot::max_value(),
|
||||||
withdrawal_slot: Slot::max_value(),
|
withdrawal_slot: Slot::max_value(),
|
||||||
|
@ -46,7 +46,7 @@ fn status_flag_from_byte(flag: u8) -> Result<Option<StatusFlags>, StatusFlagsDec
|
|||||||
pub struct Validator {
|
pub struct Validator {
|
||||||
pub pubkey: PublicKey,
|
pub pubkey: PublicKey,
|
||||||
pub withdrawal_credentials: Hash256,
|
pub withdrawal_credentials: Hash256,
|
||||||
pub proposer_slots: Slot,
|
pub proposer_slots: u64,
|
||||||
pub activation_slot: Slot,
|
pub activation_slot: Slot,
|
||||||
pub exit_slot: Slot,
|
pub exit_slot: Slot,
|
||||||
pub withdrawal_slot: Slot,
|
pub withdrawal_slot: Slot,
|
||||||
@ -70,7 +70,7 @@ impl Default for Validator {
|
|||||||
Self {
|
Self {
|
||||||
pubkey: PublicKey::default(),
|
pubkey: PublicKey::default(),
|
||||||
withdrawal_credentials: Hash256::default(),
|
withdrawal_credentials: Hash256::default(),
|
||||||
proposer_slots: Slot::from(0_u64),
|
proposer_slots: 0,
|
||||||
activation_slot: Slot::from(std::u64::MAX),
|
activation_slot: Slot::from(std::u64::MAX),
|
||||||
exit_slot: Slot::from(std::u64::MAX),
|
exit_slot: Slot::from(std::u64::MAX),
|
||||||
withdrawal_slot: Slot::from(std::u64::MAX),
|
withdrawal_slot: Slot::from(std::u64::MAX),
|
||||||
|
@ -5,3 +5,4 @@ authors = ["Paul Hauner <paul@paulhauner.com>"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
types = { path = "../../types" }
|
||||||
|
@ -3,9 +3,10 @@ mod testing_slot_clock;
|
|||||||
|
|
||||||
pub use crate::system_time_slot_clock::{Error as SystemTimeSlotClockError, SystemTimeSlotClock};
|
pub use crate::system_time_slot_clock::{Error as SystemTimeSlotClockError, SystemTimeSlotClock};
|
||||||
pub use crate::testing_slot_clock::{Error as TestingSlotClockError, TestingSlotClock};
|
pub use crate::testing_slot_clock::{Error as TestingSlotClockError, TestingSlotClock};
|
||||||
|
pub use types::Slot;
|
||||||
|
|
||||||
pub trait SlotClock: Send + Sync {
|
pub trait SlotClock: Send + Sync {
|
||||||
type Error;
|
type Error;
|
||||||
|
|
||||||
fn present_slot(&self) -> Result<Option<u64>, Self::Error>;
|
fn present_slot(&self) -> Result<Option<Slot>, Self::Error>;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use super::SlotClock;
|
use super::SlotClock;
|
||||||
use std::time::{Duration, SystemTime};
|
use std::time::{Duration, SystemTime};
|
||||||
|
use types::Slot;
|
||||||
|
|
||||||
pub use std::time::SystemTimeError;
|
pub use std::time::SystemTimeError;
|
||||||
|
|
||||||
@ -38,7 +39,7 @@ impl SystemTimeSlotClock {
|
|||||||
impl SlotClock for SystemTimeSlotClock {
|
impl SlotClock for SystemTimeSlotClock {
|
||||||
type Error = Error;
|
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 syslot_time = SystemTime::now();
|
||||||
let duration_since_epoch = syslot_time.duration_since(SystemTime::UNIX_EPOCH)?;
|
let duration_since_epoch = syslot_time.duration_since(SystemTime::UNIX_EPOCH)?;
|
||||||
let duration_since_genesis =
|
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> {
|
fn slot_from_duration(slot_duration_seconds: u64, duration: Duration) -> Option<Slot> {
|
||||||
duration.as_secs().checked_div(slot_duration_seconds)
|
Some(Slot::new(
|
||||||
|
duration.as_secs().checked_div(slot_duration_seconds)?,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -81,19 +84,19 @@ mod tests {
|
|||||||
genesis_seconds: genesis,
|
genesis_seconds: genesis,
|
||||||
slot_duration_seconds: slot_time,
|
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 {
|
let clock = SystemTimeSlotClock {
|
||||||
genesis_seconds: since_epoch.as_secs(),
|
genesis_seconds: since_epoch.as_secs(),
|
||||||
slot_duration_seconds: slot_time,
|
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 {
|
let clock = SystemTimeSlotClock {
|
||||||
genesis_seconds: since_epoch.as_secs() - slot_time * 42 - 5,
|
genesis_seconds: since_epoch.as_secs() - slot_time * 42 - 5,
|
||||||
slot_duration_seconds: slot_time,
|
slot_duration_seconds: slot_time,
|
||||||
};
|
};
|
||||||
assert_eq!(clock.present_slot().unwrap(), Some(42));
|
assert_eq!(clock.present_slot().unwrap(), Some(Slot::new(42)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -102,23 +105,23 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
slot_from_duration(slot_time, Duration::from_secs(0)),
|
slot_from_duration(slot_time, Duration::from_secs(0)),
|
||||||
Some(0)
|
Some(Slot::new(0))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
slot_from_duration(slot_time, Duration::from_secs(10)),
|
slot_from_duration(slot_time, Duration::from_secs(10)),
|
||||||
Some(0)
|
Some(Slot::new(0))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
slot_from_duration(slot_time, Duration::from_secs(100)),
|
slot_from_duration(slot_time, Duration::from_secs(100)),
|
||||||
Some(1)
|
Some(Slot::new(1))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
slot_from_duration(slot_time, Duration::from_secs(101)),
|
slot_from_duration(slot_time, Duration::from_secs(101)),
|
||||||
Some(1)
|
Some(Slot::new(1))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
slot_from_duration(slot_time, Duration::from_secs(1000)),
|
slot_from_duration(slot_time, Duration::from_secs(1000)),
|
||||||
Some(10)
|
Some(Slot::new(10))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use super::SlotClock;
|
use super::SlotClock;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
use types::Slot;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum Error {}
|
pub enum Error {}
|
||||||
@ -27,9 +28,9 @@ impl TestingSlotClock {
|
|||||||
impl SlotClock for TestingSlotClock {
|
impl SlotClock for TestingSlotClock {
|
||||||
type Error = Error;
|
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.");
|
let slot = *self.slot.read().expect("TestingSlotClock poisoned.");
|
||||||
Ok(Some(slot))
|
Ok(Some(Slot::new(slot)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,8 +41,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_slot_now() {
|
fn test_slot_now() {
|
||||||
let clock = TestingSlotClock::new(10);
|
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);
|
clock.set_slot(123);
|
||||||
assert_eq!(clock.present_slot(), Ok(Some(123)));
|
assert_eq!(clock.present_slot(), Ok(Some(Slot::new(123))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ pub fn process_deposit(
|
|||||||
let validator = Validator {
|
let validator = Validator {
|
||||||
pubkey: deposit_input.pubkey.clone(),
|
pubkey: deposit_input.pubkey.clone(),
|
||||||
withdrawal_credentials: deposit_input.withdrawal_credentials,
|
withdrawal_credentials: deposit_input.withdrawal_credentials,
|
||||||
proposer_slots: Slot::new(0),
|
proposer_slots: 0,
|
||||||
activation_slot: spec.far_future_slot,
|
activation_slot: spec.far_future_slot,
|
||||||
exit_slot: spec.far_future_slot,
|
exit_slot: spec.far_future_slot,
|
||||||
withdrawal_slot: spec.far_future_slot,
|
withdrawal_slot: spec.far_future_slot,
|
||||||
|
@ -5,7 +5,7 @@ use protos::services::{
|
|||||||
use protos::services_grpc::BeaconBlockServiceClient;
|
use protos::services_grpc::BeaconBlockServiceClient;
|
||||||
use ssz::{ssz_encode, Decodable};
|
use ssz::{ssz_encode, Decodable};
|
||||||
use std::sync::Arc;
|
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
|
/// A newtype designed to wrap the gRPC-generated service so the `BeaconNode` trait may be
|
||||||
/// implemented upon it.
|
/// implemented upon it.
|
||||||
@ -32,11 +32,11 @@ impl BeaconNode for BeaconBlockGrpcClient {
|
|||||||
/// BN is unable to find a parent block.
|
/// BN is unable to find a parent block.
|
||||||
fn produce_beacon_block(
|
fn produce_beacon_block(
|
||||||
&self,
|
&self,
|
||||||
slot: u64,
|
slot: Slot,
|
||||||
randao_reveal: &Signature,
|
randao_reveal: &Signature,
|
||||||
) -> Result<Option<BeaconBlock>, BeaconNodeError> {
|
) -> Result<Option<BeaconBlock>, BeaconNodeError> {
|
||||||
let mut req = ProduceBeaconBlockRequest::new();
|
let mut req = ProduceBeaconBlockRequest::new();
|
||||||
req.set_slot(slot);
|
req.set_slot(slot.as_u64());
|
||||||
|
|
||||||
let reply = self
|
let reply = self
|
||||||
.client
|
.client
|
||||||
@ -54,7 +54,7 @@ impl BeaconNode for BeaconBlockGrpcClient {
|
|||||||
|
|
||||||
// TODO: this conversion is incomplete; fix it.
|
// TODO: this conversion is incomplete; fix it.
|
||||||
Ok(Some(BeaconBlock {
|
Ok(Some(BeaconBlock {
|
||||||
slot: block.get_slot(),
|
slot: Slot::new(block.get_slot()),
|
||||||
parent_root: Hash256::zero(),
|
parent_root: Hash256::zero(),
|
||||||
state_root: Hash256::zero(),
|
state_root: Hash256::zero(),
|
||||||
randao_reveal,
|
randao_reveal,
|
||||||
@ -88,7 +88,7 @@ impl BeaconNode for BeaconBlockGrpcClient {
|
|||||||
|
|
||||||
// TODO: this conversion is incomplete; fix it.
|
// TODO: this conversion is incomplete; fix it.
|
||||||
let mut grpc_block = GrpcBeaconBlock::new();
|
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_block_root(vec![0]);
|
||||||
grpc_block.set_randao_reveal(ssz_encode(&block.randao_reveal));
|
grpc_block.set_randao_reveal(ssz_encode(&block.randao_reveal));
|
||||||
grpc_block.set_signature(ssz_encode(&block.signature));
|
grpc_block.set_signature(ssz_encode(&block.signature));
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use block_producer::{DutiesReader, DutiesReaderError};
|
use block_producer::{DutiesReader, DutiesReaderError};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
use types::{Epoch, Slot};
|
||||||
|
|
||||||
/// The information required for a validator to propose and attest during some epoch.
|
/// 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)]
|
#[derive(Debug, PartialEq, Clone, Copy, Default)]
|
||||||
pub struct EpochDuties {
|
pub struct EpochDuties {
|
||||||
pub validator_index: u64,
|
pub validator_index: u64,
|
||||||
pub block_production_slot: Option<u64>,
|
pub block_production_slot: Option<Slot>,
|
||||||
// Future shard info
|
// Future shard info
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EpochDuties {
|
impl EpochDuties {
|
||||||
/// Returns `true` if the supplied `slot` is a slot in which the validator should produce a
|
/// Returns `true` if the supplied `slot` is a slot in which the validator should produce a
|
||||||
/// block.
|
/// 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 {
|
match self.block_production_slot {
|
||||||
Some(s) if s == slot => true,
|
Some(s) if s == slot => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
@ -32,7 +33,7 @@ pub enum EpochDutiesMapError {
|
|||||||
/// Maps an `epoch` to some `EpochDuties` for a single validator.
|
/// Maps an `epoch` to some `EpochDuties` for a single validator.
|
||||||
pub struct EpochDutiesMap {
|
pub struct EpochDutiesMap {
|
||||||
pub epoch_length: u64,
|
pub epoch_length: u64,
|
||||||
pub map: RwLock<HashMap<u64, EpochDuties>>,
|
pub map: RwLock<HashMap<Epoch, EpochDuties>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EpochDutiesMap {
|
impl EpochDutiesMap {
|
||||||
@ -43,7 +44,7 @@ impl EpochDutiesMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, epoch: u64) -> Result<Option<EpochDuties>, EpochDutiesMapError> {
|
pub fn get(&self, epoch: Epoch) -> Result<Option<EpochDuties>, EpochDutiesMapError> {
|
||||||
let map = self.map.read().map_err(|_| EpochDutiesMapError::Poisoned)?;
|
let map = self.map.read().map_err(|_| EpochDutiesMapError::Poisoned)?;
|
||||||
match map.get(&epoch) {
|
match map.get(&epoch) {
|
||||||
Some(duties) => Ok(Some(duties.clone())),
|
Some(duties) => Ok(Some(duties.clone())),
|
||||||
@ -53,7 +54,7 @@ impl EpochDutiesMap {
|
|||||||
|
|
||||||
pub fn insert(
|
pub fn insert(
|
||||||
&self,
|
&self,
|
||||||
epoch: u64,
|
epoch: Epoch,
|
||||||
epoch_duties: EpochDuties,
|
epoch_duties: EpochDuties,
|
||||||
) -> Result<Option<EpochDuties>, EpochDutiesMapError> {
|
) -> Result<Option<EpochDuties>, EpochDutiesMapError> {
|
||||||
let mut map = self
|
let mut map = self
|
||||||
@ -65,10 +66,8 @@ impl EpochDutiesMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DutiesReader for EpochDutiesMap {
|
impl DutiesReader for EpochDutiesMap {
|
||||||
fn is_block_production_slot(&self, slot: u64) -> Result<bool, DutiesReaderError> {
|
fn is_block_production_slot(&self, slot: Slot) -> Result<bool, DutiesReaderError> {
|
||||||
let epoch = slot
|
let epoch = slot.epoch(self.epoch_length);
|
||||||
.checked_div(self.epoch_length)
|
|
||||||
.ok_or_else(|| DutiesReaderError::EpochLengthIsZero)?;
|
|
||||||
|
|
||||||
let map = self.map.read().map_err(|_| DutiesReaderError::Poisoned)?;
|
let map = self.map.read().map_err(|_| DutiesReaderError::Poisoned)?;
|
||||||
let duties = map
|
let duties = map
|
||||||
|
@ -3,7 +3,7 @@ use super::EpochDuties;
|
|||||||
use protos::services::{ProposeBlockSlotRequest, PublicKey as IndexRequest};
|
use protos::services::{ProposeBlockSlotRequest, PublicKey as IndexRequest};
|
||||||
use protos::services_grpc::ValidatorServiceClient;
|
use protos::services_grpc::ValidatorServiceClient;
|
||||||
use ssz::ssz_encode;
|
use ssz::ssz_encode;
|
||||||
use types::PublicKey;
|
use types::{Epoch, PublicKey, Slot};
|
||||||
|
|
||||||
impl BeaconNode for ValidatorServiceClient {
|
impl BeaconNode for ValidatorServiceClient {
|
||||||
/// Request the shuffling from the Beacon Node (BN).
|
/// Request the shuffling from the Beacon Node (BN).
|
||||||
@ -14,7 +14,7 @@ impl BeaconNode for ValidatorServiceClient {
|
|||||||
/// Note: presently only block production information is returned.
|
/// Note: presently only block production information is returned.
|
||||||
fn request_shuffling(
|
fn request_shuffling(
|
||||||
&self,
|
&self,
|
||||||
epoch: u64,
|
epoch: Epoch,
|
||||||
public_key: &PublicKey,
|
public_key: &PublicKey,
|
||||||
) -> Result<Option<EpochDuties>, BeaconNodeError> {
|
) -> Result<Option<EpochDuties>, BeaconNodeError> {
|
||||||
// Lookup the validator index for the supplied public key.
|
// Lookup the validator index for the supplied public key.
|
||||||
@ -29,7 +29,7 @@ impl BeaconNode for ValidatorServiceClient {
|
|||||||
|
|
||||||
let mut req = ProposeBlockSlotRequest::new();
|
let mut req = ProposeBlockSlotRequest::new();
|
||||||
req.set_validator_index(validator_index);
|
req.set_validator_index(validator_index);
|
||||||
req.set_epoch(epoch);
|
req.set_epoch(epoch.as_u64());
|
||||||
|
|
||||||
let reply = self
|
let reply = self
|
||||||
.propose_block_slot(&req)
|
.propose_block_slot(&req)
|
||||||
@ -41,6 +41,11 @@ impl BeaconNode for ValidatorServiceClient {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let block_production_slot = match block_production_slot {
|
||||||
|
Some(slot) => Some(Slot::new(slot)),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
Ok(Some(EpochDuties {
|
Ok(Some(EpochDuties {
|
||||||
validator_index,
|
validator_index,
|
||||||
block_production_slot,
|
block_production_slot,
|
||||||
|
@ -12,20 +12,20 @@ use self::traits::{BeaconNode, BeaconNodeError};
|
|||||||
use bls::PublicKey;
|
use bls::PublicKey;
|
||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::ChainSpec;
|
use types::{ChainSpec, Epoch, Slot};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
pub enum PollOutcome {
|
pub enum PollOutcome {
|
||||||
/// The `EpochDuties` were not updated during this poll.
|
/// 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.
|
/// 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
|
/// New `EpochDuties` were obtained, different to those which were previously known. This is
|
||||||
/// likely to be the result of chain re-organisation.
|
/// 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
|
/// The Beacon Node was unable to return the duties as the validator is unknown, or the
|
||||||
/// shuffling for the epoch is unknown.
|
/// shuffling for the epoch is unknown.
|
||||||
UnknownValidatorOrEpoch(u64),
|
UnknownValidatorOrEpoch(Epoch),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
@ -62,9 +62,7 @@ impl<T: SlotClock, U: BeaconNode> DutiesManager<T, U> {
|
|||||||
.map_err(|_| Error::SlotClockError)?
|
.map_err(|_| Error::SlotClockError)?
|
||||||
.ok_or(Error::SlotUnknowable)?;
|
.ok_or(Error::SlotUnknowable)?;
|
||||||
|
|
||||||
let epoch = slot
|
let epoch = slot.epoch(self.spec.epoch_length);
|
||||||
.checked_div(self.spec.epoch_length)
|
|
||||||
.ok_or(Error::EpochLengthIsZero)?;
|
|
||||||
|
|
||||||
if let Some(duties) = self.beacon_node.request_shuffling(epoch, &self.pubkey)? {
|
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.
|
// 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.
|
// Configure response from the BeaconNode.
|
||||||
let duties = EpochDuties {
|
let duties = EpochDuties {
|
||||||
validator_index: 0,
|
validator_index: 0,
|
||||||
block_production_slot: Some(10),
|
block_production_slot: Some(Slot::new(10)),
|
||||||
};
|
};
|
||||||
beacon_node.set_next_shuffling_result(Ok(Some(duties)));
|
beacon_node.set_next_shuffling_result(Ok(Some(duties)));
|
||||||
|
|
||||||
// Get the duties for the first time...
|
// 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...
|
// 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.
|
// Return new duties.
|
||||||
let duties = EpochDuties {
|
let duties = EpochDuties {
|
||||||
validator_index: 0,
|
validator_index: 0,
|
||||||
block_production_slot: Some(11),
|
block_production_slot: Some(Slot::new(11)),
|
||||||
};
|
};
|
||||||
beacon_node.set_next_shuffling_result(Ok(Some(duties)));
|
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.
|
// Return no duties.
|
||||||
beacon_node.set_next_shuffling_result(Ok(None));
|
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)))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,14 @@ use super::traits::{BeaconNode, BeaconNodeError};
|
|||||||
use super::EpochDuties;
|
use super::EpochDuties;
|
||||||
use bls::PublicKey;
|
use bls::PublicKey;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
use types::Epoch;
|
||||||
|
|
||||||
type ShufflingResult = Result<Option<EpochDuties>, BeaconNodeError>;
|
type ShufflingResult = Result<Option<EpochDuties>, BeaconNodeError>;
|
||||||
|
|
||||||
/// A test-only struct used to simulate a Beacon Node.
|
/// A test-only struct used to simulate a Beacon Node.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct TestBeaconNode {
|
pub struct TestBeaconNode {
|
||||||
pub request_shuffling_input: RwLock<Option<(u64, PublicKey)>>,
|
pub request_shuffling_input: RwLock<Option<(Epoch, PublicKey)>>,
|
||||||
pub request_shuffling_result: RwLock<Option<ShufflingResult>>,
|
pub request_shuffling_result: RwLock<Option<ShufflingResult>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ impl TestBeaconNode {
|
|||||||
|
|
||||||
impl BeaconNode for TestBeaconNode {
|
impl BeaconNode for TestBeaconNode {
|
||||||
/// Returns the value specified by the `set_next_shuffling_result`.
|
/// 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()));
|
*self.request_shuffling_input.write().unwrap() = Some((epoch, public_key.clone()));
|
||||||
match *self.request_shuffling_result.read().unwrap() {
|
match *self.request_shuffling_result.read().unwrap() {
|
||||||
Some(ref r) => r.clone(),
|
Some(ref r) => r.clone(),
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use super::EpochDuties;
|
use super::EpochDuties;
|
||||||
use bls::PublicKey;
|
use bls::PublicKey;
|
||||||
|
use types::Epoch;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum BeaconNodeError {
|
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.
|
/// Returns Ok(None) if the public key is unknown, or the shuffling for that epoch is unknown.
|
||||||
fn request_shuffling(
|
fn request_shuffling(
|
||||||
&self,
|
&self,
|
||||||
epoch: u64,
|
epoch: Epoch,
|
||||||
public_key: &PublicKey,
|
public_key: &PublicKey,
|
||||||
) -> Result<Option<EpochDuties>, BeaconNodeError>;
|
) -> Result<Option<EpochDuties>, BeaconNodeError>;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user