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:
parent
20ac1bf1f0
commit
db3b6cba6d
@ -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> {
|
||||
|
@ -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) => {
|
||||
|
@ -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),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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));
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user