Add attester to beacon chain test harness
This commit is contained in:
parent
e1698102e0
commit
5bbffcb053
@ -9,12 +9,14 @@ pub struct AttestationAggregator {
|
|||||||
store: HashMap<Vec<u8>, Attestation>,
|
store: HashMap<Vec<u8>, Attestation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum ProcessOutcome {
|
pub enum ProcessOutcome {
|
||||||
AggregationNotRequired,
|
AggregationNotRequired,
|
||||||
Aggregated,
|
Aggregated,
|
||||||
NewAttestationCreated,
|
NewAttestationCreated,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum ProcessError {
|
pub enum ProcessError {
|
||||||
BadValidatorIndex,
|
BadValidatorIndex,
|
||||||
BadSignature,
|
BadSignature,
|
47
beacon_node/beacon_chain/src/attestation_processing.rs
Normal file
47
beacon_node/beacon_chain/src/attestation_processing.rs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
use super::{BeaconChain, ClientDB, SlotClock};
|
||||||
|
pub use crate::attestation_aggregator::{ProcessError as AggregatorError, ProcessOutcome};
|
||||||
|
use crate::canonical_head::Error as HeadError;
|
||||||
|
use types::{AttestationData, Signature};
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum Error {
|
||||||
|
PresentSlotUnknown,
|
||||||
|
AggregatorError(AggregatorError),
|
||||||
|
HeadError(HeadError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, U> BeaconChain<T, U>
|
||||||
|
where
|
||||||
|
T: ClientDB,
|
||||||
|
U: SlotClock,
|
||||||
|
{
|
||||||
|
pub fn process_free_attestation(
|
||||||
|
&self,
|
||||||
|
attestation_data: &AttestationData,
|
||||||
|
signature: &Signature,
|
||||||
|
validator_index: u64,
|
||||||
|
) -> Result<ProcessOutcome, Error> {
|
||||||
|
let present_slot = self
|
||||||
|
.present_slot()
|
||||||
|
.ok_or_else(|| Error::PresentSlotUnknown)?;
|
||||||
|
let state = self.state(present_slot)?;
|
||||||
|
|
||||||
|
self.attestation_aggregator
|
||||||
|
.write()
|
||||||
|
.expect("Aggregator unlock failed.")
|
||||||
|
.process_free_attestation(&state, attestation_data, signature, validator_index)
|
||||||
|
.map_err(|e| e.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AggregatorError> for Error {
|
||||||
|
fn from(e: AggregatorError) -> Error {
|
||||||
|
Error::AggregatorError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<HeadError> for Error {
|
||||||
|
fn from(e: HeadError) -> Error {
|
||||||
|
Error::HeadError(e)
|
||||||
|
}
|
||||||
|
}
|
@ -3,11 +3,6 @@ use types::{AttestationData, Hash256};
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/*
|
|
||||||
DBError(String),
|
|
||||||
StateTransitionError(TransitionError),
|
|
||||||
PresentSlotIsNone,
|
|
||||||
*/
|
|
||||||
SlotTooOld,
|
SlotTooOld,
|
||||||
PresentSlotUnknown,
|
PresentSlotUnknown,
|
||||||
StateError,
|
StateError,
|
||||||
|
@ -2,6 +2,7 @@ use crate::{BeaconChain, CheckPoint, ClientDB, SlotClock};
|
|||||||
use std::sync::RwLockReadGuard;
|
use std::sync::RwLockReadGuard;
|
||||||
use types::{beacon_state::SlotProcessingError, BeaconBlock, BeaconState, Hash256};
|
use types::{beacon_state::SlotProcessingError, BeaconBlock, BeaconState, Hash256};
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
PastSlot,
|
PastSlot,
|
||||||
UnableToDetermineProducer,
|
UnableToDetermineProducer,
|
||||||
|
@ -52,4 +52,11 @@ where
|
|||||||
.beacon_block
|
.beacon_block
|
||||||
.slot
|
.slot
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn validator_attestion_slot_and_shard(&self, validator_index: usize) -> Option<(u64, u64)> {
|
||||||
|
let present_slot = self.present_slot()?;
|
||||||
|
let state = self.state(present_slot).ok()?;
|
||||||
|
|
||||||
|
Some(state.attestation_slot_and_shard_for_validator(validator_index, &self.spec))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
mod attestation_aggregation;
|
mod attestation_aggregator;
|
||||||
|
pub mod attestation_processing;
|
||||||
mod attestation_production;
|
mod attestation_production;
|
||||||
mod attestation_targets;
|
mod attestation_targets;
|
||||||
mod block_graph;
|
mod block_graph;
|
||||||
@ -14,7 +15,7 @@ mod state_transition;
|
|||||||
|
|
||||||
use self::attestation_targets::AttestationTargets;
|
use self::attestation_targets::AttestationTargets;
|
||||||
use self::block_graph::BlockGraph;
|
use self::block_graph::BlockGraph;
|
||||||
use attestation_aggregation::AttestationAggregator;
|
use attestation_aggregator::AttestationAggregator;
|
||||||
use db::{
|
use db::{
|
||||||
stores::{BeaconBlockStore, BeaconStateStore},
|
stores::{BeaconBlockStore, BeaconStateStore},
|
||||||
ClientDB, DBError,
|
ClientDB, DBError,
|
||||||
|
@ -12,11 +12,13 @@ harness = false
|
|||||||
criterion = "0.2"
|
criterion = "0.2"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
attester = { path = "../../../eth2/attester" }
|
||||||
beacon_chain = { path = "../../beacon_chain" }
|
beacon_chain = { path = "../../beacon_chain" }
|
||||||
block_producer = { path = "../../../eth2/block_producer" }
|
block_producer = { path = "../../../eth2/block_producer" }
|
||||||
bls = { path = "../../../eth2/utils/bls" }
|
bls = { path = "../../../eth2/utils/bls" }
|
||||||
boolean-bitfield = { path = "../../../eth2/utils/boolean-bitfield" }
|
boolean-bitfield = { path = "../../../eth2/utils/boolean-bitfield" }
|
||||||
db = { path = "../../db" }
|
db = { path = "../../db" }
|
||||||
|
parking_lot = "0.7"
|
||||||
failure = "0.1"
|
failure = "0.1"
|
||||||
failure_derive = "0.1"
|
failure_derive = "0.1"
|
||||||
genesis = { path = "../../../eth2/genesis" }
|
genesis = { path = "../../../eth2/genesis" }
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
use beacon_chain::block_processing::{Error as ProcessingError, Outcome as ProcessingOutcome};
|
|
||||||
use beacon_chain::{block_production::Error as BlockProductionError, BeaconChain};
|
|
||||||
use block_producer::{
|
|
||||||
BeaconNode as BeaconBlockNode, BeaconNodeError as BeaconBlockNodeError, PublishOutcome,
|
|
||||||
};
|
|
||||||
use db::ClientDB;
|
|
||||||
use slot_clock::SlotClock;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use types::{BeaconBlock, PublicKey, Signature};
|
|
||||||
|
|
||||||
pub struct DirectBeaconNode<T: ClientDB, U: SlotClock> {
|
|
||||||
beacon_chain: Arc<BeaconChain<T, U>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ClientDB, U: SlotClock> DirectBeaconNode<T, U> {
|
|
||||||
pub fn new(beacon_chain: Arc<BeaconChain<T, U>>) -> Self {
|
|
||||||
Self { beacon_chain }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ClientDB, U: SlotClock> BeaconBlockNode for DirectBeaconNode<T, U>
|
|
||||||
where
|
|
||||||
BlockProductionError: From<<U>::Error>,
|
|
||||||
ProcessingError: From<<U as SlotClock>::Error>,
|
|
||||||
{
|
|
||||||
fn proposer_nonce(&self, pubkey: &PublicKey) -> Result<u64, BeaconBlockNodeError> {
|
|
||||||
let validator_index = self
|
|
||||||
.beacon_chain
|
|
||||||
.validator_index(pubkey)
|
|
||||||
.ok_or_else(|| BeaconBlockNodeError::RemoteFailure("pubkey unknown.".to_string()))?;
|
|
||||||
|
|
||||||
self.beacon_chain
|
|
||||||
.proposer_slots(validator_index)
|
|
||||||
.ok_or_else(|| {
|
|
||||||
BeaconBlockNodeError::RemoteFailure("validator_index unknown.".to_string())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn produce_beacon_block(
|
|
||||||
&self,
|
|
||||||
slot: u64,
|
|
||||||
randao_reveal: &Signature,
|
|
||||||
) -> Result<Option<BeaconBlock>, BeaconBlockNodeError>
|
|
||||||
where {
|
|
||||||
let (block, _state) = self
|
|
||||||
.beacon_chain
|
|
||||||
.produce_block(randao_reveal.clone())
|
|
||||||
.map_err(|e| BeaconBlockNodeError::RemoteFailure(format!("{:?}", e)))?;
|
|
||||||
|
|
||||||
if block.slot == slot {
|
|
||||||
Ok(Some(block))
|
|
||||||
} else {
|
|
||||||
Err(BeaconBlockNodeError::RemoteFailure(
|
|
||||||
"Unable to produce at non-current slot.".to_string(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn publish_beacon_block(
|
|
||||||
&self,
|
|
||||||
block: BeaconBlock,
|
|
||||||
) -> Result<PublishOutcome, BeaconBlockNodeError> {
|
|
||||||
match self.beacon_chain.process_block(block) {
|
|
||||||
Ok(ProcessingOutcome::ValidBlock(_)) => Ok(PublishOutcome::ValidBlock),
|
|
||||||
Ok(ProcessingOutcome::InvalidBlock(reason)) => {
|
|
||||||
Ok(PublishOutcome::InvalidBlock(format!("{:?}", reason)))
|
|
||||||
}
|
|
||||||
Err(error) => Err(BeaconBlockNodeError::RemoteFailure(format!("{:?}", error))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
use beacon_chain::{block_production::Error as BlockProductionError, BeaconChain};
|
|
||||||
use block_producer::{DutiesReader, DutiesReaderError};
|
|
||||||
use db::ClientDB;
|
|
||||||
use slot_clock::SlotClock;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use types::PublicKey;
|
|
||||||
|
|
||||||
pub struct DirectDuties<T: ClientDB, U: SlotClock> {
|
|
||||||
beacon_chain: Arc<BeaconChain<T, U>>,
|
|
||||||
pubkey: PublicKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ClientDB, U: SlotClock> DirectDuties<T, U> {
|
|
||||||
pub fn new(pubkey: PublicKey, beacon_chain: Arc<BeaconChain<T, U>>) -> Self {
|
|
||||||
Self {
|
|
||||||
beacon_chain,
|
|
||||||
pubkey,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ClientDB, U: SlotClock> DutiesReader for DirectDuties<T, U>
|
|
||||||
where
|
|
||||||
BlockProductionError: From<<U>::Error>,
|
|
||||||
{
|
|
||||||
fn is_block_production_slot(&self, slot: u64) -> Result<bool, DutiesReaderError> {
|
|
||||||
let validator_index = self
|
|
||||||
.beacon_chain
|
|
||||||
.validator_index(&self.pubkey)
|
|
||||||
.ok_or_else(|| DutiesReaderError::UnknownValidator)?;
|
|
||||||
|
|
||||||
match self.beacon_chain.block_proposer(slot) {
|
|
||||||
Some(proposer) if proposer == validator_index => Ok(true),
|
|
||||||
Some(_) => Ok(false),
|
|
||||||
None => Err(DutiesReaderError::UnknownEpoch),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +1,5 @@
|
|||||||
mod beacon_chain_harness;
|
mod harness;
|
||||||
mod benching_beacon_node;
|
|
||||||
mod direct_beacon_node;
|
|
||||||
mod direct_duties;
|
|
||||||
mod validator;
|
mod validator;
|
||||||
|
|
||||||
pub use self::beacon_chain_harness::BeaconChainHarness;
|
pub use self::harness::BeaconChainHarness;
|
||||||
pub use self::benching_beacon_node::BenchingBeaconNode;
|
|
||||||
pub use self::direct_beacon_node::DirectBeaconNode;
|
|
||||||
pub use self::direct_duties::DirectDuties;
|
|
||||||
pub use self::validator::TestValidator;
|
pub use self::validator::TestValidator;
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
use super::BenchingBeaconNode;
|
||||||
|
use attester::{BeaconNode as AttesterBeaconNode, BeaconNodeError as NodeError, PublishOutcome};
|
||||||
|
use beacon_chain::block_processing::Error as ProcessingError;
|
||||||
|
use beacon_chain::block_production::Error as BlockProductionError;
|
||||||
|
use db::ClientDB;
|
||||||
|
use slot_clock::SlotClock;
|
||||||
|
use types::{AttestationData, Signature};
|
||||||
|
|
||||||
|
impl<T: ClientDB, U: SlotClock> AttesterBeaconNode for BenchingBeaconNode<T, U>
|
||||||
|
where
|
||||||
|
BlockProductionError: From<<U>::Error>,
|
||||||
|
ProcessingError: From<<U as SlotClock>::Error>,
|
||||||
|
{
|
||||||
|
fn produce_attestation_data(
|
||||||
|
&self,
|
||||||
|
slot: u64,
|
||||||
|
shard: u64,
|
||||||
|
) -> Result<Option<AttestationData>, NodeError> {
|
||||||
|
match self.beacon_chain.produce_attestation_data(slot, shard) {
|
||||||
|
Ok(attestation_data) => Ok(Some(attestation_data)),
|
||||||
|
Err(e) => Err(NodeError::RemoteFailure(format!("{:?}", e))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn publish_attestation_data(
|
||||||
|
&self,
|
||||||
|
attestation_data: AttestationData,
|
||||||
|
signature: Signature,
|
||||||
|
validator_index: u64,
|
||||||
|
) -> Result<PublishOutcome, NodeError> {
|
||||||
|
match self.beacon_chain.process_free_attestation(
|
||||||
|
&attestation_data,
|
||||||
|
&signature,
|
||||||
|
validator_index,
|
||||||
|
) {
|
||||||
|
Ok(_) => Ok(PublishOutcome::ValidAttestation),
|
||||||
|
Err(e) => Err(NodeError::RemoteFailure(format!("{:?}", e))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
use beacon_chain::BeaconChain;
|
||||||
|
use db::ClientDB;
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
use slot_clock::SlotClock;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use types::{AttestationData, BeaconBlock, Signature};
|
||||||
|
|
||||||
|
mod attester;
|
||||||
|
mod producer;
|
||||||
|
|
||||||
|
/// An attestation that hasn't been aggregated into an `Attestation`.
|
||||||
|
///
|
||||||
|
/// (attestation_data, signature, validator_index)
|
||||||
|
pub type FreeAttestation = (AttestationData, Signature, u64);
|
||||||
|
|
||||||
|
pub struct BenchingBeaconNode<T: ClientDB, U: SlotClock> {
|
||||||
|
beacon_chain: Arc<BeaconChain<T, U>>,
|
||||||
|
published_blocks: RwLock<Vec<BeaconBlock>>,
|
||||||
|
published_attestations: RwLock<Vec<FreeAttestation>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ClientDB, U: SlotClock> BenchingBeaconNode<T, U> {
|
||||||
|
pub fn new(beacon_chain: Arc<BeaconChain<T, U>>) -> Self {
|
||||||
|
Self {
|
||||||
|
beacon_chain,
|
||||||
|
published_blocks: RwLock::new(vec![]),
|
||||||
|
published_attestations: RwLock::new(vec![]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn last_published_block(&self) -> Option<BeaconBlock> {
|
||||||
|
Some(self.published_blocks.read().last()?.clone())
|
||||||
|
}
|
||||||
|
}
|
@ -1,37 +1,13 @@
|
|||||||
|
use super::BenchingBeaconNode;
|
||||||
use beacon_chain::block_processing::Error as ProcessingError;
|
use beacon_chain::block_processing::Error as ProcessingError;
|
||||||
use beacon_chain::{block_production::Error as BlockProductionError, BeaconChain};
|
use beacon_chain::block_production::Error as BlockProductionError;
|
||||||
use block_producer::{
|
use block_producer::{
|
||||||
BeaconNode as BeaconBlockNode, BeaconNodeError as BeaconBlockNodeError, PublishOutcome,
|
BeaconNode as BeaconBlockNode, BeaconNodeError as BeaconBlockNodeError, PublishOutcome,
|
||||||
};
|
};
|
||||||
use db::ClientDB;
|
use db::ClientDB;
|
||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
use std::sync::{Arc, RwLock};
|
|
||||||
use types::{BeaconBlock, PublicKey, Signature};
|
use types::{BeaconBlock, PublicKey, Signature};
|
||||||
|
|
||||||
pub struct BenchingBeaconNode<T: ClientDB, U: SlotClock> {
|
|
||||||
beacon_chain: Arc<BeaconChain<T, U>>,
|
|
||||||
published_blocks: RwLock<Vec<BeaconBlock>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ClientDB, U: SlotClock> BenchingBeaconNode<T, U> {
|
|
||||||
pub fn new(beacon_chain: Arc<BeaconChain<T, U>>) -> Self {
|
|
||||||
Self {
|
|
||||||
beacon_chain,
|
|
||||||
published_blocks: RwLock::new(vec![]),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn last_published_block(&self) -> Option<BeaconBlock> {
|
|
||||||
Some(
|
|
||||||
self.published_blocks
|
|
||||||
.read()
|
|
||||||
.expect("Unable to unlock `published_blocks` for reading.")
|
|
||||||
.last()?
|
|
||||||
.clone(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ClientDB, U: SlotClock> BeaconBlockNode for BenchingBeaconNode<T, U>
|
impl<T: ClientDB, U: SlotClock> BeaconBlockNode for BenchingBeaconNode<T, U>
|
||||||
where
|
where
|
||||||
BlockProductionError: From<<U>::Error>,
|
BlockProductionError: From<<U>::Error>,
|
||||||
@ -56,8 +32,7 @@ where
|
|||||||
&self,
|
&self,
|
||||||
slot: u64,
|
slot: u64,
|
||||||
randao_reveal: &Signature,
|
randao_reveal: &Signature,
|
||||||
) -> Result<Option<BeaconBlock>, BeaconBlockNodeError>
|
) -> Result<Option<BeaconBlock>, BeaconBlockNodeError> {
|
||||||
where {
|
|
||||||
let (block, _state) = self
|
let (block, _state) = self
|
||||||
.beacon_chain
|
.beacon_chain
|
||||||
.produce_block(randao_reveal.clone())
|
.produce_block(randao_reveal.clone())
|
||||||
@ -81,10 +56,7 @@ where {
|
|||||||
&self,
|
&self,
|
||||||
block: BeaconBlock,
|
block: BeaconBlock,
|
||||||
) -> Result<PublishOutcome, BeaconBlockNodeError> {
|
) -> Result<PublishOutcome, BeaconBlockNodeError> {
|
||||||
self.published_blocks
|
self.published_blocks.write().push(block);
|
||||||
.write()
|
|
||||||
.expect("Unable to unlock `published_blocks` for writing.")
|
|
||||||
.push(block);
|
|
||||||
Ok(PublishOutcome::ValidBlock)
|
Ok(PublishOutcome::ValidBlock)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
use attester::{
|
||||||
|
DutiesReader as AttesterDutiesReader, DutiesReaderError as AttesterDutiesReaderError,
|
||||||
|
};
|
||||||
|
use beacon_chain::{block_production::Error as BlockProductionError, BeaconChain};
|
||||||
|
use block_producer::{
|
||||||
|
DutiesReader as ProducerDutiesReader, DutiesReaderError as ProducerDutiesReaderError,
|
||||||
|
};
|
||||||
|
use db::ClientDB;
|
||||||
|
use slot_clock::SlotClock;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use types::PublicKey;
|
||||||
|
|
||||||
|
pub struct DirectDuties<T: ClientDB, U: SlotClock> {
|
||||||
|
beacon_chain: Arc<BeaconChain<T, U>>,
|
||||||
|
pubkey: PublicKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ClientDB, U: SlotClock> DirectDuties<T, U> {
|
||||||
|
pub fn new(pubkey: PublicKey, beacon_chain: Arc<BeaconChain<T, U>>) -> Self {
|
||||||
|
Self {
|
||||||
|
beacon_chain,
|
||||||
|
pubkey,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ClientDB, U: SlotClock> ProducerDutiesReader for DirectDuties<T, U>
|
||||||
|
where
|
||||||
|
BlockProductionError: From<<U>::Error>,
|
||||||
|
{
|
||||||
|
fn is_block_production_slot(&self, slot: u64) -> Result<bool, ProducerDutiesReaderError> {
|
||||||
|
let validator_index = self
|
||||||
|
.beacon_chain
|
||||||
|
.validator_index(&self.pubkey)
|
||||||
|
.ok_or_else(|| ProducerDutiesReaderError::UnknownValidator)?;
|
||||||
|
|
||||||
|
match self.beacon_chain.block_proposer(slot) {
|
||||||
|
Some(proposer) if proposer == validator_index => Ok(true),
|
||||||
|
Some(_) => Ok(false),
|
||||||
|
None => Err(ProducerDutiesReaderError::UnknownEpoch),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ClientDB, U: SlotClock> AttesterDutiesReader for DirectDuties<T, U>
|
||||||
|
where
|
||||||
|
BlockProductionError: From<<U>::Error>,
|
||||||
|
{
|
||||||
|
fn validator_index(&self) -> Option<u64> {
|
||||||
|
match self.beacon_chain.validator_index(&self.pubkey) {
|
||||||
|
Some(index) => Some(index as u64),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn attestation_shard(&self, slot: u64) -> Result<Option<u64>, AttesterDutiesReaderError> {
|
||||||
|
if let Some(validator_index) = self.validator_index() {
|
||||||
|
match self
|
||||||
|
.beacon_chain
|
||||||
|
.validator_attestion_slot_and_shard(validator_index as usize)
|
||||||
|
{
|
||||||
|
Some((attest_slot, attest_shard)) if attest_slot == slot => Ok(Some(attest_shard)),
|
||||||
|
Some(_) => Ok(None),
|
||||||
|
None => Err(AttesterDutiesReaderError::UnknownEpoch),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(AttesterDutiesReaderError::UnknownValidator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,18 @@
|
|||||||
use super::{BenchingBeaconNode, DirectDuties};
|
use attester::Attester;
|
||||||
use beacon_chain::BeaconChain;
|
use beacon_chain::BeaconChain;
|
||||||
use block_producer::{test_utils::TestSigner, BlockProducer, Error as PollError};
|
use block_producer::{BlockProducer, Error as PollError};
|
||||||
use db::MemoryDB;
|
use db::MemoryDB;
|
||||||
|
use signer::TestSigner;
|
||||||
use slot_clock::TestingSlotClock;
|
use slot_clock::TestingSlotClock;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::{BeaconBlock, ChainSpec, Keypair};
|
use types::{BeaconBlock, ChainSpec, Keypair};
|
||||||
|
|
||||||
|
mod beacon_node;
|
||||||
|
mod direct_duties;
|
||||||
|
mod signer;
|
||||||
|
|
||||||
|
pub use self::beacon_node::BenchingBeaconNode;
|
||||||
|
pub use self::direct_duties::DirectDuties;
|
||||||
pub use block_producer::PollOutcome;
|
pub use block_producer::PollOutcome;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
@ -21,6 +28,12 @@ pub struct TestValidator {
|
|||||||
DirectDuties<MemoryDB, TestingSlotClock>,
|
DirectDuties<MemoryDB, TestingSlotClock>,
|
||||||
TestSigner,
|
TestSigner,
|
||||||
>,
|
>,
|
||||||
|
pub attester: Attester<
|
||||||
|
TestingSlotClock,
|
||||||
|
BenchingBeaconNode<MemoryDB, TestingSlotClock>,
|
||||||
|
DirectDuties<MemoryDB, TestingSlotClock>,
|
||||||
|
TestSigner,
|
||||||
|
>,
|
||||||
pub spec: Arc<ChainSpec>,
|
pub spec: Arc<ChainSpec>,
|
||||||
pub epoch_map: Arc<DirectDuties<MemoryDB, TestingSlotClock>>,
|
pub epoch_map: Arc<DirectDuties<MemoryDB, TestingSlotClock>>,
|
||||||
pub keypair: Keypair,
|
pub keypair: Keypair,
|
||||||
@ -49,8 +62,16 @@ impl TestValidator {
|
|||||||
signer.clone(),
|
signer.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let attester = Attester::new(
|
||||||
|
epoch_map.clone(),
|
||||||
|
slot_clock.clone(),
|
||||||
|
beacon_node.clone(),
|
||||||
|
signer.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
block_producer,
|
block_producer,
|
||||||
|
attester,
|
||||||
spec,
|
spec,
|
||||||
epoch_map,
|
epoch_map,
|
||||||
keypair,
|
keypair,
|
@ -0,0 +1,46 @@
|
|||||||
|
use attester::Signer as AttesterSigner;
|
||||||
|
use block_producer::Signer as BlockProposerSigner;
|
||||||
|
use std::sync::RwLock;
|
||||||
|
use types::{Keypair, Signature};
|
||||||
|
|
||||||
|
/// A test-only struct used to simulate a Beacon Node.
|
||||||
|
pub struct TestSigner {
|
||||||
|
keypair: Keypair,
|
||||||
|
should_sign: RwLock<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestSigner {
|
||||||
|
/// Produce a new TestSigner with signing enabled by default.
|
||||||
|
pub fn new(keypair: Keypair) -> Self {
|
||||||
|
Self {
|
||||||
|
keypair,
|
||||||
|
should_sign: RwLock::new(true),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If set to `false`, the service will refuse to sign all messages. Otherwise, all messages
|
||||||
|
/// will be signed.
|
||||||
|
pub fn enable_signing(&self, enabled: bool) {
|
||||||
|
*self.should_sign.write().unwrap() = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bls_sign(&self, message: &[u8]) -> Option<Signature> {
|
||||||
|
Some(Signature::new(message, &self.keypair.sk))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockProposerSigner for TestSigner {
|
||||||
|
fn sign_block_proposal(&self, message: &[u8]) -> Option<Signature> {
|
||||||
|
self.bls_sign(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sign_randao_reveal(&self, message: &[u8]) -> Option<Signature> {
|
||||||
|
self.bls_sign(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AttesterSigner for TestSigner {
|
||||||
|
fn sign_attestation_message(&self, message: &[u8]) -> Option<Signature> {
|
||||||
|
self.bls_sign(message)
|
||||||
|
}
|
||||||
|
}
|
@ -131,7 +131,7 @@ impl<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> Attester<T, U, V,
|
|||||||
self.store_produce(attestation_data);
|
self.store_produce(attestation_data);
|
||||||
|
|
||||||
self.signer
|
self.signer
|
||||||
.bls_sign(&attestation_data.signable_message(PHASE_0_CUSTODY_BIT)[..])
|
.sign_attestation_message(&attestation_data.signable_message(PHASE_0_CUSTODY_BIT)[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if signing some attestation_data is safe (non-slashable).
|
/// Returns `true` if signing some attestation_data is safe (non-slashable).
|
||||||
|
@ -25,7 +25,7 @@ impl TestSigner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Signer for TestSigner {
|
impl Signer for TestSigner {
|
||||||
fn bls_sign(&self, message: &[u8]) -> Option<Signature> {
|
fn sign_attestation_message(&self, message: &[u8]) -> Option<Signature> {
|
||||||
Some(Signature::new(message, &self.keypair.sk))
|
Some(Signature::new(message, &self.keypair.sk))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,5 +47,5 @@ pub trait DutiesReader: Send + Sync {
|
|||||||
|
|
||||||
/// Signs message using an internally-maintained private key.
|
/// Signs message using an internally-maintained private key.
|
||||||
pub trait Signer {
|
pub trait Signer {
|
||||||
fn bls_sign(&self, message: &[u8]) -> Option<Signature>;
|
fn sign_attestation_message(&self, message: &[u8]) -> Option<Signature>;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ mod traits;
|
|||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
use ssz::ssz_encode;
|
use ssz::ssz_encode;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::{BeaconBlock, ChainSpec, Hash256, ProposalSignedData, PublicKey};
|
use types::{BeaconBlock, ChainSpec, PublicKey};
|
||||||
|
|
||||||
pub use self::traits::{
|
pub use self::traits::{
|
||||||
BeaconNode, BeaconNodeError, DutiesReader, DutiesReaderError, PublishOutcome, Signer,
|
BeaconNode, BeaconNodeError, DutiesReader, DutiesReaderError, PublishOutcome, Signer,
|
||||||
@ -139,7 +139,7 @@ impl<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> BlockProducer<T, U
|
|||||||
// TODO: add domain, etc to this message.
|
// TODO: add domain, etc to this message.
|
||||||
let message = ssz_encode(&producer_nonce);
|
let message = ssz_encode(&producer_nonce);
|
||||||
|
|
||||||
match self.signer.bls_sign(&message) {
|
match self.signer.sign_randao_reveal(&message) {
|
||||||
None => return Ok(PollOutcome::SignerRejection(slot)),
|
None => return Ok(PollOutcome::SignerRejection(slot)),
|
||||||
Some(signature) => signature,
|
Some(signature) => signature,
|
||||||
}
|
}
|
||||||
@ -171,7 +171,10 @@ impl<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> BlockProducer<T, U
|
|||||||
fn sign_block(&mut self, mut block: BeaconBlock) -> Option<BeaconBlock> {
|
fn sign_block(&mut self, mut block: BeaconBlock) -> Option<BeaconBlock> {
|
||||||
self.store_produce(&block);
|
self.store_produce(&block);
|
||||||
|
|
||||||
match self.signer.bls_sign(&block.proposal_root(&self.spec)[..]) {
|
match self
|
||||||
|
.signer
|
||||||
|
.sign_block_proposal(&block.proposal_root(&self.spec)[..])
|
||||||
|
{
|
||||||
None => None,
|
None => None,
|
||||||
Some(signature) => {
|
Some(signature) => {
|
||||||
block.signature = signature;
|
block.signature = signature;
|
||||||
|
@ -25,7 +25,11 @@ impl TestSigner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Signer for TestSigner {
|
impl Signer for TestSigner {
|
||||||
fn bls_sign(&self, message: &[u8]) -> Option<Signature> {
|
fn sign_block_proposal(&self, message: &[u8]) -> Option<Signature> {
|
||||||
|
Some(Signature::new(message, &self.keypair.sk))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sign_randao_reveal(&self, message: &[u8]) -> Option<Signature> {
|
||||||
Some(Signature::new(message, &self.keypair.sk))
|
Some(Signature::new(message, &self.keypair.sk))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,5 +47,6 @@ pub trait DutiesReader: Send + Sync {
|
|||||||
|
|
||||||
/// Signs message using an internally-maintained private key.
|
/// Signs message using an internally-maintained private key.
|
||||||
pub trait Signer {
|
pub trait Signer {
|
||||||
fn bls_sign(&self, message: &[u8]) -> Option<Signature>;
|
fn sign_block_proposal(&self, message: &[u8]) -> Option<Signature>;
|
||||||
|
fn sign_randao_reveal(&self, message: &[u8]) -> Option<Signature>;
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,20 @@ impl BeaconState {
|
|||||||
let validator_count = self.validator_registry.len();
|
let validator_count = self.validator_registry.len();
|
||||||
Some((slot as usize) % validator_count)
|
Some((slot as usize) % validator_count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn attestation_slot_and_shard_for_validator(
|
||||||
|
&self,
|
||||||
|
validator_index: usize,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> (u64, u64) {
|
||||||
|
// TODO: this is a stub; implement it properly.
|
||||||
|
let validator_index = validator_index as u64;
|
||||||
|
|
||||||
|
let slot = validator_index % spec.epoch_length;
|
||||||
|
let shard = validator_index % spec.shard_count;
|
||||||
|
|
||||||
|
(slot, shard)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merkle_root(_input: &[Hash256]) -> Hash256 {
|
fn merkle_root(_input: &[Hash256]) -> Hash256 {
|
||||||
|
Loading…
Reference in New Issue
Block a user