diff --git a/beacon_node/beacon_chain/test_harness/src/validator_harness/direct_duties.rs b/beacon_node/beacon_chain/test_harness/src/validator_harness/direct_duties.rs index 5bed59531..dec93c334 100644 --- a/beacon_node/beacon_chain/test_harness/src/validator_harness/direct_duties.rs +++ b/beacon_node/beacon_chain/test_harness/src/validator_harness/direct_duties.rs @@ -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 ProducerDutiesReader for DirectDu Err(_) => Err(ProducerDutiesReaderError::UnknownEpoch), } } + + fn fork(&self) -> Result { + Ok(self.beacon_chain.state.read().fork.clone()) + } } impl AttesterDutiesReader for DirectDuties { diff --git a/eth2/block_proposer/src/lib.rs b/eth2/block_proposer/src/lib.rs index 55461d986..5cddbaedc 100644 --- a/eth2/block_proposer/src/lib.rs +++ b/eth2/block_proposer/src/lib.rs @@ -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 BlockProducer Result { + 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 BlockProducer BlockProducer Option { + fn sign_block(&mut self, mut block: BeaconBlock, domain: u64) -> Option { self.store_produce(&block); let proposal = Proposal { @@ -182,7 +191,7 @@ impl BlockProducer None, Some(signature) => { diff --git a/eth2/block_proposer/src/test_utils/epoch_map.rs b/eth2/block_proposer/src/test_utils/epoch_map.rs index f7d8dcdcb..6658c7526 100644 --- a/eth2/block_proposer/src/test_utils/epoch_map.rs +++ b/eth2/block_proposer/src/test_utils/epoch_map.rs @@ -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 { + Ok(Fork { + previous_version: 0, + current_version: 0, + epoch: Epoch::new(0), + }) + } } diff --git a/eth2/block_proposer/src/traits.rs b/eth2/block_proposer/src/traits.rs index c6e57d833..1c0da9acf 100644 --- a/eth2/block_proposer/src/traits.rs +++ b/eth2/block_proposer/src/traits.rs @@ -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; + fn fork(&self) -> Result; } /// Signs message using an internally-maintained private key. diff --git a/validator_client/src/block_producer_service/mod.rs b/validator_client/src/block_producer_service/mod.rs index bd1e691cb..91e7606a7 100644 --- a/validator_client/src/block_producer_service/mod.rs +++ b/validator_client/src/block_producer_service/mod.rs @@ -50,6 +50,9 @@ impl 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)); diff --git a/validator_client/src/duties/epoch_duties.rs b/validator_client/src/duties/epoch_duties.rs index d1bbfa156..35668b4a9 100644 --- a/validator_client/src/duties/epoch_duties.rs +++ b/validator_client/src/duties/epoch_duties.rs @@ -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 { + // 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.