Update EpochDuty RPC and core functionality
This commit is contained in:
parent
96ccd58414
commit
bc8ec51fe5
@ -26,10 +26,9 @@ service BeaconBlockService {
|
||||
/// Service that provides the validator client with requisite knowledge about
|
||||
//its public keys
|
||||
service ValidatorService {
|
||||
rpc ProposeBlockSlot(ProposeBlockSlotRequest) returns (ProposeBlockSlotResponse);
|
||||
/// Given a set of public keys, returns their respective indicies
|
||||
rpc ValidatorIndex(PublicKeys) returns (Indicies);
|
||||
// rpc ValidatorAssignment(ValidatorAssignmentRequest) returns (ValidatorAssignmentResponse);
|
||||
// Gets the block proposer slot and comittee slot that a validator needs to
|
||||
// perform work on.
|
||||
rpc GetValidatorDuties(GetDutiesRequest) returns (GetDutiesResponse);
|
||||
}
|
||||
|
||||
/// Service that handles validator attestations
|
||||
@ -93,58 +92,41 @@ message BeaconBlock {
|
||||
/*
|
||||
* Validator Service Messages
|
||||
*/
|
||||
/*
|
||||
message ValidatorAssignmentRequest {
|
||||
uint64 epoch = 1;
|
||||
bytes validator_index = 2;
|
||||
}
|
||||
|
||||
// A validators duties for some epoch.
|
||||
// TODO: add shard duties.
|
||||
message ValidatorAssignment {
|
||||
oneof block_production_slot_oneof {
|
||||
bool block_production_slot_none = 1;
|
||||
uint64 block_production_slot = 2;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Validator Assignment
|
||||
|
||||
message PublicKeys {
|
||||
// the public keys of the validators
|
||||
message Validators {
|
||||
repeated bytes public_key = 1;
|
||||
}
|
||||
|
||||
message Indicies {
|
||||
repeated uint64 index = 1;
|
||||
}
|
||||
|
||||
|
||||
// Propose slot
|
||||
|
||||
message ProposeBlockSlotRequest {
|
||||
message GetDutiesRequest {
|
||||
uint64 epoch = 1;
|
||||
repeated uint64 validator_index = 2;
|
||||
Validators validators = 2;
|
||||
}
|
||||
|
||||
message GetDutiesResponse {
|
||||
repeated oneof slot_oneof {
|
||||
repeated ActiveValidator active_validator = 1;
|
||||
}
|
||||
|
||||
message ActiveValidator {
|
||||
oneof slot_oneof {
|
||||
bool none = 1;
|
||||
ValidatorDuty duty = 2;
|
||||
}
|
||||
}
|
||||
|
||||
ValidatorDuty {
|
||||
message ValidatorDuty {
|
||||
oneof block_oneof {
|
||||
bool none = 1;
|
||||
uint64 block_produce_slot = 2;
|
||||
}
|
||||
uint64 committee_slot = 1;
|
||||
uint64 committee_shard = 2;
|
||||
uint64 committee_index = 3;
|
||||
uint64 committee_slot = 3;
|
||||
uint64 committee_shard = 4;
|
||||
uint64 committee_index = 5;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Attestation Service Messages
|
||||
*/
|
||||
|
@ -1,30 +1,40 @@
|
||||
use block_proposer::{DutiesReader, DutiesReaderError};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::RwLock;
|
||||
use types::{Epoch, Fork, Slot};
|
||||
use types::{Epoch, Fork, PublicKey, Slot};
|
||||
|
||||
/// The information required for a validator to propose and attest during some epoch.
|
||||
///
|
||||
/// Generally obtained from a Beacon Node, this information contains the validators canonical index
|
||||
/// (thier sequence in the global validator induction process) and the "shuffling" for that index
|
||||
/// (their sequence in the global validator induction process) and the "shuffling" for that index
|
||||
/// for some epoch.
|
||||
#[derive(Debug, PartialEq, Clone, Copy, Default)]
|
||||
pub struct EpochDuties {
|
||||
pub validator_index: u64,
|
||||
pub struct EpochDuty {
|
||||
pub block_production_slot: Option<Slot>,
|
||||
// Future shard info
|
||||
pub committee_slot: Slot,
|
||||
pub committee_shard: u64,
|
||||
pub committee_index: u64,
|
||||
}
|
||||
|
||||
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: Slot) -> bool {
|
||||
impl EpochDuty {
|
||||
/// Returns `true` if work needs to be done in the supplied `slot`
|
||||
pub fn is_work_slot(&self, slot: Slot) -> bool {
|
||||
// if validator is required to produce a slot return true
|
||||
match self.block_production_slot {
|
||||
Some(s) if s == slot => true,
|
||||
Some(s) if s == slot => return true,
|
||||
_ => false,
|
||||
}
|
||||
|
||||
if self.committee_slot == slot {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// Maps a list of public keys (many validators) to an EpochDuty.
|
||||
pub struct EpochDuties {
|
||||
inner: HashMap<PublicKey, Option<EpochDuty>>,
|
||||
}
|
||||
|
||||
pub enum EpochDutiesMapError {
|
||||
Poisoned,
|
||||
|
@ -1,56 +1,54 @@
|
||||
use super::epoch_duties::{EpochDuties, EpochDuty};
|
||||
use super::traits::{BeaconNode, BeaconNodeError};
|
||||
use super::EpochDuties;
|
||||
use protos::services::{ProposeBlockSlotRequest, PublicKeys as IndexRequest};
|
||||
use protos::services::{
|
||||
ActiveValidator, GetDutiesRequest, GetDutiesResponse, ValidatorDuty, Validators,
|
||||
};
|
||||
use protos::services_grpc::ValidatorServiceClient;
|
||||
use ssz::ssz_encode;
|
||||
use std::collections::HashMap;
|
||||
use types::{Epoch, PublicKey, Slot};
|
||||
|
||||
impl BeaconNode for ValidatorServiceClient {
|
||||
/// Request the shuffling from the Beacon Node (BN).
|
||||
///
|
||||
/// As this function takes a `PublicKey`, it will first attempt to resolve the public key into
|
||||
/// a validator index, then call the BN for production/attestation duties.
|
||||
///
|
||||
/// Note: presently only block production information is returned.
|
||||
fn request_shuffling(
|
||||
/// Requests all duties (block signing and committee attesting) from the Beacon Node (BN).
|
||||
fn request_duties(
|
||||
&self,
|
||||
epoch: Epoch,
|
||||
pubkeys: &[PublicKey],
|
||||
) -> Result<Option<EpochDuties>, BeaconNodeError> {
|
||||
// Lookup the validator indexes for all the supplied public keys.
|
||||
let validator_indices = {
|
||||
let mut req = IndexRequest::new();
|
||||
for public_key in pubkeys {
|
||||
req.mut_public_key().push(ssz_encode(public_key));
|
||||
}
|
||||
let resp = self
|
||||
.validator_index(&req)
|
||||
.map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?;
|
||||
resp.get_index()
|
||||
};
|
||||
|
||||
let mut req = ProposeBlockSlotRequest::new();
|
||||
req.set_validator_index(validator_index);
|
||||
) -> Result<EpochDuties, BeaconNodeError> {
|
||||
// Get the required duties from all validators
|
||||
// build the request
|
||||
let mut req = GetDutiesRequest::new();
|
||||
req.set_epoch(epoch.as_u64());
|
||||
let validators = Validators::new().mut_public_key();
|
||||
for pubkey in pubkeys {
|
||||
validators.push(pubkey);
|
||||
}
|
||||
req.set_validators(validators);
|
||||
|
||||
// send the request, get the duties reply
|
||||
let reply = self
|
||||
.propose_block_slot(&req)
|
||||
.get_validator_duties(&req)
|
||||
.map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?;
|
||||
|
||||
let block_production_slot = if reply.has_slot() {
|
||||
Some(reply.get_slot())
|
||||
} else {
|
||||
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,
|
||||
}))
|
||||
let mut epoch_duties: HashMap<PublicKey, Option<EpochDuties>> = HashMap::new();
|
||||
for (index, validator_duty) in reply.get_active_validator().enumerate() {
|
||||
if let Some(duty) = validator_duty.has_slot() {
|
||||
// the validator is active
|
||||
//build the EpochDuty
|
||||
let active_duty = duty.get_duty();
|
||||
let block_produce_slot = active_duty.get_block_produce_slot();
|
||||
let epoch_duty = EpochDuty {
|
||||
block_produce_slot,
|
||||
committee_slot: active_duty.get_committee_slot(),
|
||||
committee_shard: active_duty.get_committee_shard(),
|
||||
committee_index: active_duty.get_committee_index(),
|
||||
};
|
||||
epoch_duties.insert(pubkeys[index], Some(epoch_duty));
|
||||
} else {
|
||||
// validator is not active and has no duties
|
||||
epoch_duties.insert(pubkeys[index], None);
|
||||
}
|
||||
}
|
||||
Ok(epoch_duties)
|
||||
}
|
||||
}
|
||||
|
@ -8,12 +8,13 @@ pub enum BeaconNodeError {
|
||||
|
||||
/// Defines the methods required to obtain a validators shuffling from a Beacon Node.
|
||||
pub trait BeaconNode: Send + Sync {
|
||||
/// Get the shuffling for the given epoch and public key.
|
||||
/// Gets the duties for all validators.
|
||||
///
|
||||
/// Returns Ok(None) if the public key is unknown, or the shuffling for that epoch is unknown.
|
||||
fn request_shuffling(
|
||||
/// Returns a vector of EpochDuties for each validator public key. The entry will be None for
|
||||
/// validators that are not activated.
|
||||
fn request_duties(
|
||||
&self,
|
||||
epoch: Epoch,
|
||||
pubkeys: &[PublicKey],
|
||||
) -> Result<Option<EpochDuties>, BeaconNodeError>;
|
||||
) -> Result<Vec<Option<EpochDuties>>, BeaconNodeError>;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user