From 643fc20063c9af9e6df9f4f1ebd4f347ce76c282 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Fri, 25 Jan 2019 11:29:41 +1100 Subject: [PATCH] Update block_producer for upstream changes --- eth2/block_producer/src/lib.rs | 46 +++++++++++-------- .../src/test_utils/beacon_node.rs | 4 +- .../src/test_utils/epoch_map.rs | 19 ++++++-- eth2/block_producer/src/traits.rs | 10 +++- 4 files changed, 52 insertions(+), 27 deletions(-) diff --git a/eth2/block_producer/src/lib.rs b/eth2/block_producer/src/lib.rs index 48c36fa9f..3cf610355 100644 --- a/eth2/block_producer/src/lib.rs +++ b/eth2/block_producer/src/lib.rs @@ -7,7 +7,9 @@ use ssz::ssz_encode; use std::sync::{Arc, RwLock}; use types::{BeaconBlock, Hash256, ProposalSignedData, PublicKey}; -pub use self::traits::{BeaconNode, BeaconNodeError, DutiesReader, DutiesReaderError, Signer}; +pub use self::traits::{ + BeaconNode, BeaconNodeError, DutiesReader, DutiesReaderError, PublishOutcome, Signer, +}; #[derive(Debug, PartialEq)] pub enum PollOutcome { @@ -46,11 +48,11 @@ pub enum Error { /// /// Relies upon an external service to keep the `EpochDutiesMap` updated. pub struct BlockProducer { - pub last_processed_slot: u64, + pub last_processed_slot: Option, pubkey: PublicKey, spec: Arc, epoch_map: Arc, - slot_clock: Arc>, + slot_clock: Arc, beacon_node: Arc, signer: Arc, } @@ -61,12 +63,12 @@ impl BlockProducer, pubkey: PublicKey, epoch_map: Arc, - slot_clock: Arc>, + slot_clock: Arc, beacon_node: Arc, signer: Arc, ) -> Self { Self { - last_processed_slot: 0, + last_processed_slot: None, pubkey, spec, epoch_map, @@ -84,8 +86,6 @@ impl BlockProducer Result { let slot = self .slot_clock - .read() - .map_err(|_| Error::SlotClockPoisoned)? .present_slot() .map_err(|_| Error::SlotClockError)? .ok_or(Error::SlotUnknowable)?; @@ -95,21 +95,20 @@ impl BlockProducer self.last_processed_slot { - let is_block_production_slot = - match self.epoch_map.is_block_production_slot(epoch, slot) { - Ok(result) => result, - Err(DutiesReaderError::UnknownEpoch) => { - return Ok(PollOutcome::ProducerDutiesUnknown(slot)) - } - Err(DutiesReaderError::UnknownValidator) => { - return Ok(PollOutcome::ValidatorIsUnknown(slot)) - } - Err(DutiesReaderError::Poisoned) => return Err(Error::EpochMapPoisoned), - }; + if !self.is_processed_slot(slot) { + let is_block_production_slot = match self.epoch_map.is_block_production_slot(slot) { + Ok(result) => result, + Err(DutiesReaderError::UnknownEpoch) => { + return Ok(PollOutcome::ProducerDutiesUnknown(slot)) + } + Err(DutiesReaderError::UnknownValidator) => { + return Ok(PollOutcome::ValidatorIsUnknown(slot)) + } + Err(DutiesReaderError::Poisoned) => return Err(Error::EpochMapPoisoned), + }; if is_block_production_slot { - self.last_processed_slot = slot; + self.last_processed_slot = Some(slot); self.produce_block(slot) } else { @@ -120,6 +119,13 @@ impl BlockProducer bool { + match self.last_processed_slot { + Some(processed_slot) if processed_slot <= slot => true, + _ => false, + } + } + /// Produce a block at some slot. /// /// Assumes that a block is required at this slot (does not check the duties). diff --git a/eth2/block_producer/src/test_utils/beacon_node.rs b/eth2/block_producer/src/test_utils/beacon_node.rs index 59527ce60..f132ce6ec 100644 --- a/eth2/block_producer/src/test_utils/beacon_node.rs +++ b/eth2/block_producer/src/test_utils/beacon_node.rs @@ -1,10 +1,10 @@ -use crate::traits::{BeaconNode, BeaconNodeError}; +use crate::traits::{BeaconNode, BeaconNodeError, PublishOutcome}; use std::sync::RwLock; use types::{BeaconBlock, PublicKey, Signature}; type NonceResult = Result; type ProduceResult = Result, BeaconNodeError>; -type PublishResult = Result; +type PublishResult = Result; /// A test-only struct used to simulate a Beacon Node. #[derive(Default)] diff --git a/eth2/block_producer/src/test_utils/epoch_map.rs b/eth2/block_producer/src/test_utils/epoch_map.rs index 290660afd..4cb1fb9fb 100644 --- a/eth2/block_producer/src/test_utils/epoch_map.rs +++ b/eth2/block_producer/src/test_utils/epoch_map.rs @@ -1,11 +1,24 @@ use crate::{DutiesReader, DutiesReaderError}; use std::collections::HashMap; -pub type TestEpochMap = HashMap; +pub struct TestEpochMap { + epoch_length: u64, + map: HashMap, +} + +impl TestEpochMap { + fn new(epoch_length: u64) -> Self { + Self { + epoch_length, + map: HashMap::new(), + } + } +} impl DutiesReader for TestEpochMap { - fn is_block_production_slot(&self, epoch: u64, slot: u64) -> Result { - match self.get(&epoch) { + fn is_block_production_slot(&self, slot: u64) -> Result { + let epoch = slot / self.epoch_length; + match self.map.get(&epoch) { Some(s) if *s == slot => Ok(true), Some(s) if *s != slot => Ok(false), _ => Err(DutiesReaderError::UnknownEpoch), diff --git a/eth2/block_producer/src/traits.rs b/eth2/block_producer/src/traits.rs index 0145328a3..dada6ce3a 100644 --- a/eth2/block_producer/src/traits.rs +++ b/eth2/block_producer/src/traits.rs @@ -6,6 +6,12 @@ pub enum BeaconNodeError { DecodeFailure, } +#[derive(Debug, PartialEq, Clone)] +pub enum PublishOutcome { + ValidBlock, + InvalidBlock(String), +} + /// Defines the methods required to produce and publish blocks on a Beacon Node. pub trait BeaconNode: Send + Sync { /// Requests the proposer nonce (presently named `proposer_slots`). @@ -23,7 +29,7 @@ pub trait BeaconNode: Send + Sync { /// Request that the node publishes a block. /// /// Returns `true` if the publish was sucessful. - fn publish_beacon_block(&self, block: BeaconBlock) -> Result; + fn publish_beacon_block(&self, block: BeaconBlock) -> Result; } #[derive(Debug, PartialEq, Clone)] @@ -35,7 +41,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, epoch: u64, slot: u64) -> Result; + fn is_block_production_slot(&self, slot: u64) -> Result; } /// Signs message using an internally-maintained private key.