Implements Signer generic for validator client and epoch duties

This commit is contained in:
Age Manning
2019-03-30 14:27:37 +11:00
parent ba771282fa
commit d3a6d73153
8 changed files with 70 additions and 36 deletions

View File

@@ -1,5 +1,5 @@
use super::EpochDuties;
use types::{Epoch, Keypair};
use types::{Epoch, PublicKey};
#[derive(Debug, PartialEq, Clone)]
pub enum BeaconNodeDutiesError {
@@ -15,6 +15,6 @@ pub trait BeaconNodeDuties: Send + Sync {
fn request_duties(
&self,
epoch: Epoch,
signers: &[Keypair],
pub_keys: &[PublicKey],
) -> Result<EpochDuties, BeaconNodeDutiesError>;
}

View File

@@ -1,7 +1,7 @@
use std::collections::HashMap;
use std::fmt;
use std::ops::{Deref, DerefMut};
use types::{AttestationDuty, Epoch, Keypair, Slot};
use types::{AttestationDuty, Epoch, PublicKey, Slot};
/// When work needs to be performed by a validator, this type is given back to the main service
/// which indicates all the information that required to process the work.
@@ -72,7 +72,7 @@ impl fmt::Display for EpochDuty {
}
/// Maps a list of keypairs (many validators) to an EpochDuty.
pub type EpochDuties = HashMap<Keypair, Option<EpochDuty>>;
pub type EpochDuties = HashMap<PublicKey, Option<EpochDuty>>;
pub enum EpochDutiesMapError {
UnknownEpoch,
@@ -113,7 +113,7 @@ impl EpochDutiesMap {
pub fn is_work_slot(
&self,
slot: Slot,
signer: &Keypair,
signer: &PublicKey,
) -> Result<Option<WorkInfo>, EpochDutiesMapError> {
let epoch = slot.epoch(self.slots_per_epoch);

View File

@@ -6,21 +6,21 @@ use protos::services_grpc::ValidatorServiceClient;
use ssz::ssz_encode;
use std::collections::HashMap;
use std::time::Duration;
use types::{Epoch, Keypair, Slot};
use types::{Epoch, PublicKey, Slot};
impl BeaconNodeDuties for ValidatorServiceClient {
/// Requests all duties (block signing and committee attesting) from the Beacon Node (BN).
fn request_duties(
&self,
epoch: Epoch,
signers: &[Keypair],
pub_keys: &[PublicKey],
) -> Result<EpochDuties, BeaconNodeDutiesError> {
// Get the required duties from all validators
// build the request
let mut req = GetDutiesRequest::new();
req.set_epoch(epoch.as_u64());
let mut validators = Validators::new();
validators.set_public_keys(signers.iter().map(|v| ssz_encode(&v.pk)).collect());
validators.set_public_keys(pub_keys.iter().map(|v| ssz_encode(v)).collect());
req.set_validators(validators);
// set a timeout for requests
@@ -31,11 +31,11 @@ impl BeaconNodeDuties for ValidatorServiceClient {
.get_validator_duties(&req)
.map_err(|err| BeaconNodeDutiesError::RemoteFailure(format!("{:?}", err)))?;
let mut epoch_duties: HashMap<Keypair, Option<EpochDuty>> = HashMap::new();
let mut epoch_duties: HashMap<PublicKey, Option<EpochDuty>> = HashMap::new();
for (index, validator_duty) in reply.get_active_validators().iter().enumerate() {
if !validator_duty.has_duty() {
// validator is inactive
epoch_duties.insert(signers[index].clone(), None);
epoch_duties.insert(pub_keys[index].clone(), None);
continue;
}
// active validator
@@ -53,7 +53,7 @@ impl BeaconNodeDuties for ValidatorServiceClient {
attestation_shard: active_duty.get_attestation_shard(),
committee_index: active_duty.get_committee_index(),
};
epoch_duties.insert(signers[index].clone(), Some(epoch_duty));
epoch_duties.insert(pub_keys[index].clone(), Some(epoch_duty));
}
Ok(epoch_duties)
}

View File

@@ -8,11 +8,13 @@ mod grpc;
pub use self::beacon_node_duties::{BeaconNodeDuties, BeaconNodeDutiesError};
use self::epoch_duties::{EpochDuties, EpochDutiesMapError};
pub use self::epoch_duties::{EpochDutiesMap, WorkInfo};
use super::signer::Signer;
use futures::Async;
use slog::{debug, error, info};
use std::fmt::Display;
use std::sync::Arc;
use std::sync::RwLock;
use types::{Epoch, Keypair, Slot};
use types::{Epoch, PublicKey, Slot};
#[derive(Debug, PartialEq, Clone)]
pub enum UpdateOutcome {
@@ -38,20 +40,20 @@ pub enum Error {
/// Node.
///
/// This keeps track of all validator keys and required voting slots.
pub struct DutiesManager<U: BeaconNodeDuties> {
pub struct DutiesManager<U: BeaconNodeDuties, S: Signer> {
pub duties_map: RwLock<EpochDutiesMap>,
/// A list of all signer objects known to the validator service.
// TODO: Generalise the signers, so that they're not just keypairs
pub signers: Arc<Vec<Keypair>>,
pub signers: Arc<Vec<S>>,
pub beacon_node: Arc<U>,
}
impl<U: BeaconNodeDuties> DutiesManager<U> {
impl<U: BeaconNodeDuties, S: Signer + Display> DutiesManager<U, S> {
/// Check the Beacon Node for `EpochDuties`.
///
/// be a wall-clock (e.g., system time, remote server time, etc.).
fn update(&self, epoch: Epoch) -> Result<UpdateOutcome, Error> {
let duties = self.beacon_node.request_duties(epoch, &self.signers)?;
let public_keys: Vec<PublicKey> = self.signers.iter().map(|s| s.to_public()).collect();
let duties = self.beacon_node.request_duties(epoch, &public_keys)?;
{
// If these duties were known, check to see if they're updates or identical.
if let Some(known_duties) = self.duties_map.read()?.get(&epoch) {
@@ -90,17 +92,17 @@ impl<U: BeaconNodeDuties> DutiesManager<U> {
Ok(Async::Ready(()))
}
/// Returns a list of (Public, WorkInfo) indicating all the validators that have work to perform
/// Returns a list of (index, WorkInfo) indicating all the validators that have work to perform
/// this slot.
pub fn get_current_work(&self, slot: Slot) -> Option<Vec<(Keypair, WorkInfo)>> {
let mut current_work: Vec<(Keypair, WorkInfo)> = Vec::new();
pub fn get_current_work(&self, slot: Slot) -> Option<Vec<(usize, WorkInfo)>> {
let mut current_work: Vec<(usize, WorkInfo)> = Vec::new();
// if the map is poisoned, return None
let duties = self.duties_map.read().ok()?;
for validator_signer in self.signers.iter() {
match duties.is_work_slot(slot, &validator_signer) {
Ok(Some(work_type)) => current_work.push((validator_signer.clone(), work_type)),
for (index, validator_signer) in self.signers.iter().enumerate() {
match duties.is_work_slot(slot, &validator_signer.to_public()) {
Ok(Some(work_type)) => current_work.push((index, work_type)),
Ok(None) => {} // No work for this validator
//TODO: This should really log an error, as we shouldn't end up with an err here.
Err(_) => {} // Unknown epoch or validator, no work