Introduce Fork struct to block_producer

It's a pretty crappy solution, IMO. It shouldn't really belong in
"duties" but this gets the job done for now.
This commit is contained in:
Paul Hauner 2019-03-07 13:54:56 +11:00
parent 20ac1bf1f0
commit db3b6cba6d
No known key found for this signature in database
GPG Key ID: D362883A9218FCC6
6 changed files with 54 additions and 18 deletions

View File

@ -9,7 +9,7 @@ use db::ClientDB;
use fork_choice::ForkChoice;
use slot_clock::SlotClock;
use std::sync::Arc;
use types::{PublicKey, Slot};
use types::{Fork, PublicKey, Slot};
/// Connects directly to a borrowed `BeaconChain` and reads attester/proposer duties directly from
/// it.
@ -40,6 +40,10 @@ impl<T: ClientDB, U: SlotClock, F: ForkChoice> ProducerDutiesReader for DirectDu
Err(_) => Err(ProducerDutiesReaderError::UnknownEpoch),
}
}
fn fork(&self) -> Result<Fork, ProducerDutiesReaderError> {
Ok(self.beacon_chain.state.read().fork.clone())
}
}
impl<T: ClientDB, U: SlotClock, F: ForkChoice> AttesterDutiesReader for DirectDuties<T, U, F> {

View File

@ -1,19 +1,15 @@
pub mod test_utils;
mod traits;
use int_to_bytes::int_to_bytes32;
use slot_clock::SlotClock;
use ssz::SignedRoot;
use ssz::{SignedRoot, TreeHash};
use std::sync::Arc;
use types::{BeaconBlock, ChainSpec, Hash256, Proposal, Slot};
use types::{BeaconBlock, ChainSpec, Domain, Hash256, Proposal, Slot};
pub use self::traits::{
BeaconNode, BeaconNodeError, DutiesReader, DutiesReaderError, PublishOutcome, Signer,
};
//TODO: obtain the correct domain using a `Fork`.
pub const TEMPORARY_DOMAIN_VALUE: u64 = 0;
#[derive(Debug, PartialEq)]
pub enum PollOutcome {
/// A new block was produced.
@ -32,6 +28,8 @@ pub enum PollOutcome {
SignerRejection(Slot),
/// The public key for this validator is not an active validator.
ValidatorIsUnknown(Slot),
/// Unable to determine a `Fork` for signature domain generation.
UnableToGetFork(Slot),
}
#[derive(Debug, PartialEq)]
@ -134,14 +132,20 @@ 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
/// slashing.
fn produce_block(&mut self, slot: Slot) -> Result<PollOutcome, Error> {
let fork = match self.epoch_map.fork() {
Ok(fork) => fork,
Err(_) => return Ok(PollOutcome::UnableToGetFork(slot)),
};
let randao_reveal = {
// TODO: add domain, etc to this message. Also ensure result matches `into_to_bytes32`.
let message = int_to_bytes32(slot.epoch(self.spec.slots_per_epoch).as_u64());
let message = slot.epoch(self.spec.slots_per_epoch).hash_tree_root();
match self
.signer
.sign_randao_reveal(&message, TEMPORARY_DOMAIN_VALUE)
{
match self.signer.sign_randao_reveal(
&message,
self.spec
.get_domain(slot.epoch(self.spec.slots_per_epoch), Domain::Randao, &fork),
) {
None => return Ok(PollOutcome::SignerRejection(slot)),
Some(signature) => signature,
}
@ -152,7 +156,12 @@ impl<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> BlockProducer<T, U
.produce_beacon_block(slot, &randao_reveal)?
{
if self.safe_to_produce(&block) {
if let Some(block) = self.sign_block(block) {
let domain = self.spec.get_domain(
slot.epoch(self.spec.slots_per_epoch),
Domain::Proposal,
&fork,
);
if let Some(block) = self.sign_block(block, domain) {
self.beacon_node.publish_beacon_block(block)?;
Ok(PollOutcome::BlockProduced(slot))
} else {
@ -170,7 +179,7 @@ impl<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> BlockProducer<T, U
///
/// Important: this function will not check to ensure the block is not slashable. This must be
/// done upstream.
fn sign_block(&mut self, mut block: BeaconBlock) -> Option<BeaconBlock> {
fn sign_block(&mut self, mut block: BeaconBlock, domain: u64) -> Option<BeaconBlock> {
self.store_produce(&block);
let proposal = Proposal {
@ -182,7 +191,7 @@ impl<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> BlockProducer<T, U
match self
.signer
.sign_block_proposal(&proposal.signed_root()[..], TEMPORARY_DOMAIN_VALUE)
.sign_block_proposal(&proposal.signed_root()[..], domain)
{
None => None,
Some(signature) => {

View File

@ -1,6 +1,6 @@
use crate::{DutiesReader, DutiesReaderError};
use std::collections::HashMap;
use types::{Epoch, Slot};
use types::{Epoch, Fork, Slot};
pub struct EpochMap {
slots_per_epoch: u64,
@ -25,4 +25,12 @@ impl DutiesReader for EpochMap {
_ => Err(DutiesReaderError::UnknownEpoch),
}
}
fn fork(&self) -> Result<Fork, DutiesReaderError> {
Ok(Fork {
previous_version: 0,
current_version: 0,
epoch: Epoch::new(0),
})
}
}

View File

@ -1,4 +1,4 @@
use types::{BeaconBlock, Signature, Slot};
use types::{BeaconBlock, Fork, Signature, Slot};
#[derive(Debug, PartialEq, Clone)]
pub enum BeaconNodeError {
@ -40,6 +40,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: Slot) -> Result<bool, DutiesReaderError>;
fn fork(&self) -> Result<Fork, DutiesReaderError>;
}
/// Signs message using an internally-maintained private key.

View File

@ -50,6 +50,9 @@ impl<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> BlockProducerServi
Ok(BlockProducerPollOutcome::ValidatorIsUnknown(slot)) => {
error!(self.log, "The Beacon Node does not recognise the validator"; "slot" => slot)
}
Ok(BlockProducerPollOutcome::UnableToGetFork(slot)) => {
error!(self.log, "Unable to get a `Fork` struct to generate signature domains"; "slot" => slot)
}
};
std::thread::sleep(Duration::from_millis(self.poll_interval_millis));

View File

@ -1,7 +1,7 @@
use block_proposer::{DutiesReader, DutiesReaderError};
use std::collections::HashMap;
use std::sync::RwLock;
use types::{Epoch, Slot};
use types::{Epoch, Fork, Slot};
/// The information required for a validator to propose and attest during some epoch.
///
@ -75,6 +75,17 @@ impl DutiesReader for EpochDutiesMap {
.ok_or_else(|| DutiesReaderError::UnknownEpoch)?;
Ok(duties.is_block_production_slot(slot))
}
fn fork(&self) -> Result<Fork, DutiesReaderError> {
// TODO: this is garbage data.
//
// It will almost certainly cause signatures to fail verification.
Ok(Fork {
previous_version: 0,
current_version: 0,
epoch: Epoch::new(0),
})
}
}
// TODO: add tests.