From 4008ec9b25c56ca29e22140dc549d7b7f251d20c Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 5 Feb 2019 05:49:53 +1100 Subject: [PATCH] Re-org test_harness files for consistency --- .../src/validator/beacon_node/attester.rs | 26 ---- .../src/validator/beacon_node/mod.rs | 41 ------ .../src/validator/beacon_node/producer.rs | 58 -------- .../src/validator/direct_beacon_node.rs | 121 ++++++++++++++++ .../test_harness/src/validator/mod.rs | 137 +----------------- .../test_harness/src/validator/validator.rs | 133 +++++++++++++++++ 6 files changed, 257 insertions(+), 259 deletions(-) delete mode 100644 beacon_node/beacon_chain/test_harness/src/validator/beacon_node/attester.rs delete mode 100644 beacon_node/beacon_chain/test_harness/src/validator/beacon_node/mod.rs delete mode 100644 beacon_node/beacon_chain/test_harness/src/validator/beacon_node/producer.rs create mode 100644 beacon_node/beacon_chain/test_harness/src/validator/direct_beacon_node.rs create mode 100644 beacon_node/beacon_chain/test_harness/src/validator/validator.rs diff --git a/beacon_node/beacon_chain/test_harness/src/validator/beacon_node/attester.rs b/beacon_node/beacon_chain/test_harness/src/validator/beacon_node/attester.rs deleted file mode 100644 index e7198461e..000000000 --- a/beacon_node/beacon_chain/test_harness/src/validator/beacon_node/attester.rs +++ /dev/null @@ -1,26 +0,0 @@ -use super::DirectBeaconNode; -use attester::{BeaconNode as AttesterBeaconNode, BeaconNodeError as NodeError, PublishOutcome}; -use db::ClientDB; -use slot_clock::SlotClock; -use types::{AttestationData, FreeAttestation}; - -impl AttesterBeaconNode for DirectBeaconNode { - fn produce_attestation_data( - &self, - _slot: u64, - shard: u64, - ) -> Result, NodeError> { - match self.beacon_chain.produce_attestation_data(shard) { - Ok(attestation_data) => Ok(Some(attestation_data)), - Err(e) => Err(NodeError::RemoteFailure(format!("{:?}", e))), - } - } - - fn publish_attestation_data( - &self, - free_attestation: FreeAttestation, - ) -> Result { - self.published_attestations.write().push(free_attestation); - Ok(PublishOutcome::ValidAttestation) - } -} diff --git a/beacon_node/beacon_chain/test_harness/src/validator/beacon_node/mod.rs b/beacon_node/beacon_chain/test_harness/src/validator/beacon_node/mod.rs deleted file mode 100644 index 90f8943fc..000000000 --- a/beacon_node/beacon_chain/test_harness/src/validator/beacon_node/mod.rs +++ /dev/null @@ -1,41 +0,0 @@ -use beacon_chain::BeaconChain; -use db::ClientDB; -use parking_lot::RwLock; -use slot_clock::SlotClock; -use std::sync::Arc; -use types::{BeaconBlock, FreeAttestation}; - -mod attester; -mod producer; - -/// Connect directly to a borrowed `BeaconChain` instance so an attester/producer can request/submit -/// blocks/attestations. -/// -/// `BeaconBlock`s and `FreeAttestation`s are not actually published to the `BeaconChain`, instead -/// they are stored inside this struct. This is to allow one to benchmark the submission of the -/// block/attestation directly, or modify it before submission. -pub struct DirectBeaconNode { - beacon_chain: Arc>, - published_blocks: RwLock>, - published_attestations: RwLock>, -} - -impl DirectBeaconNode { - pub fn new(beacon_chain: Arc>) -> Self { - Self { - beacon_chain, - published_blocks: RwLock::new(vec![]), - published_attestations: RwLock::new(vec![]), - } - } - - /// Get the last published block (if any). - pub fn last_published_block(&self) -> Option { - Some(self.published_blocks.read().last()?.clone()) - } - - /// Get the last published attestation (if any). - pub fn last_published_free_attestation(&self) -> Option { - Some(self.published_attestations.read().last()?.clone()) - } -} diff --git a/beacon_node/beacon_chain/test_harness/src/validator/beacon_node/producer.rs b/beacon_node/beacon_chain/test_harness/src/validator/beacon_node/producer.rs deleted file mode 100644 index d188d8554..000000000 --- a/beacon_node/beacon_chain/test_harness/src/validator/beacon_node/producer.rs +++ /dev/null @@ -1,58 +0,0 @@ -use super::DirectBeaconNode; -use block_producer::{ - BeaconNode as BeaconBlockNode, BeaconNodeError as BeaconBlockNodeError, PublishOutcome, -}; -use db::ClientDB; -use slot_clock::SlotClock; -use types::{BeaconBlock, PublicKey, Signature}; - -impl BeaconBlockNode for DirectBeaconNode { - /// Requests the `proposer_nonce` from the `BeaconChain`. - fn proposer_nonce(&self, pubkey: &PublicKey) -> Result { - 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()) - }) - } - - /// Requests a new `BeaconBlock from the `BeaconChain`. - fn produce_beacon_block( - &self, - slot: u64, - randao_reveal: &Signature, - ) -> Result, BeaconBlockNodeError> { - let (block, _state) = self - .beacon_chain - .produce_block(randao_reveal.clone()) - .ok_or_else(|| { - BeaconBlockNodeError::RemoteFailure(format!("Did not produce block.")) - })?; - - if block.slot == slot { - Ok(Some(block)) - } else { - Err(BeaconBlockNodeError::RemoteFailure( - "Unable to produce at non-current slot.".to_string(), - )) - } - } - - /// A block is not _actually_ published to the `BeaconChain`, instead it is stored in the - /// `published_block_vec` and a successful `ValidBlock` is returned to the caller. - /// - /// The block may be retrieved and then applied to the `BeaconChain` manually, potentially in a - /// benchmarking scenario. - fn publish_beacon_block( - &self, - block: BeaconBlock, - ) -> Result { - self.published_blocks.write().push(block); - Ok(PublishOutcome::ValidBlock) - } -} diff --git a/beacon_node/beacon_chain/test_harness/src/validator/direct_beacon_node.rs b/beacon_node/beacon_chain/test_harness/src/validator/direct_beacon_node.rs new file mode 100644 index 000000000..ed71f28d3 --- /dev/null +++ b/beacon_node/beacon_chain/test_harness/src/validator/direct_beacon_node.rs @@ -0,0 +1,121 @@ +use attester::{ + BeaconNode as AttesterBeaconNode, BeaconNodeError as NodeError, + PublishOutcome as AttestationPublishOutcome, +}; +use beacon_chain::BeaconChain; +use block_producer::{ + BeaconNode as BeaconBlockNode, BeaconNodeError as BeaconBlockNodeError, + PublishOutcome as BlockPublishOutcome, +}; +use db::ClientDB; +use parking_lot::RwLock; +use slot_clock::SlotClock; +use std::sync::Arc; +use types::{AttestationData, BeaconBlock, FreeAttestation, PublicKey, Signature}; + +// mod attester; +// mod producer; + +/// Connect directly to a borrowed `BeaconChain` instance so an attester/producer can request/submit +/// blocks/attestations. +/// +/// `BeaconBlock`s and `FreeAttestation`s are not actually published to the `BeaconChain`, instead +/// they are stored inside this struct. This is to allow one to benchmark the submission of the +/// block/attestation directly, or modify it before submission. +pub struct DirectBeaconNode { + beacon_chain: Arc>, + published_blocks: RwLock>, + published_attestations: RwLock>, +} + +impl DirectBeaconNode { + pub fn new(beacon_chain: Arc>) -> Self { + Self { + beacon_chain, + published_blocks: RwLock::new(vec![]), + published_attestations: RwLock::new(vec![]), + } + } + + /// Get the last published block (if any). + pub fn last_published_block(&self) -> Option { + Some(self.published_blocks.read().last()?.clone()) + } + + /// Get the last published attestation (if any). + pub fn last_published_free_attestation(&self) -> Option { + Some(self.published_attestations.read().last()?.clone()) + } +} + +impl AttesterBeaconNode for DirectBeaconNode { + fn produce_attestation_data( + &self, + _slot: u64, + shard: u64, + ) -> Result, NodeError> { + match self.beacon_chain.produce_attestation_data(shard) { + Ok(attestation_data) => Ok(Some(attestation_data)), + Err(e) => Err(NodeError::RemoteFailure(format!("{:?}", e))), + } + } + + fn publish_attestation_data( + &self, + free_attestation: FreeAttestation, + ) -> Result { + self.published_attestations.write().push(free_attestation); + Ok(AttestationPublishOutcome::ValidAttestation) + } +} + +impl BeaconBlockNode for DirectBeaconNode { + /// Requests the `proposer_nonce` from the `BeaconChain`. + fn proposer_nonce(&self, pubkey: &PublicKey) -> Result { + 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()) + }) + } + + /// Requests a new `BeaconBlock from the `BeaconChain`. + fn produce_beacon_block( + &self, + slot: u64, + randao_reveal: &Signature, + ) -> Result, BeaconBlockNodeError> { + let (block, _state) = self + .beacon_chain + .produce_block(randao_reveal.clone()) + .ok_or_else(|| { + BeaconBlockNodeError::RemoteFailure(format!("Did not produce block.")) + })?; + + if block.slot == slot { + Ok(Some(block)) + } else { + Err(BeaconBlockNodeError::RemoteFailure( + "Unable to produce at non-current slot.".to_string(), + )) + } + } + + /// A block is not _actually_ published to the `BeaconChain`, instead it is stored in the + /// `published_block_vec` and a successful `ValidBlock` is returned to the caller. + /// + /// The block may be retrieved and then applied to the `BeaconChain` manually, potentially in a + /// benchmarking scenario. + fn publish_beacon_block( + &self, + block: BeaconBlock, + ) -> Result { + self.published_blocks.write().push(block); + Ok(BlockPublishOutcome::ValidBlock) + } +} diff --git a/beacon_node/beacon_chain/test_harness/src/validator/mod.rs b/beacon_node/beacon_chain/test_harness/src/validator/mod.rs index 4eae0bb3a..3a0d53395 100644 --- a/beacon_node/beacon_chain/test_harness/src/validator/mod.rs +++ b/beacon_node/beacon_chain/test_harness/src/validator/mod.rs @@ -1,137 +1,6 @@ -use attester::{Attester, Error as AttestationPollError}; -use beacon_chain::BeaconChain; -use block_producer::{BlockProducer, Error as BlockPollError}; -use db::MemoryDB; -use signer::TestSigner; -use slot_clock::TestingSlotClock; -use std::sync::Arc; -use types::{BeaconBlock, ChainSpec, FreeAttestation, Keypair}; -mod beacon_node; +mod direct_beacon_node; mod direct_duties; mod signer; +mod validator; -pub use self::beacon_node::DirectBeaconNode; -pub use self::direct_duties::DirectDuties; -pub use attester::PollOutcome as AttestationPollOutcome; -pub use block_producer::PollOutcome as BlockPollOutcome; - -#[derive(Debug, PartialEq)] -pub enum BlockProduceError { - DidNotProduce(BlockPollOutcome), - PollError(BlockPollError), -} - -#[derive(Debug, PartialEq)] -pub enum AttestationProduceError { - DidNotProduce(AttestationPollOutcome), - PollError(AttestationPollError), -} - -/// A `BlockProducer` and `Attester` which sign using a common keypair. -/// -/// The test validator connects directly to a borrowed `BeaconChain` struct. It is useful for -/// testing that the core proposer and attester logic is functioning. Also for supporting beacon -/// chain tests. -pub struct TestValidator { - pub block_producer: BlockProducer< - TestingSlotClock, - DirectBeaconNode, - DirectDuties, - TestSigner, - >, - pub attester: Attester< - TestingSlotClock, - DirectBeaconNode, - DirectDuties, - TestSigner, - >, - pub spec: Arc, - pub epoch_map: Arc>, - pub keypair: Keypair, - pub beacon_node: Arc>, - pub slot_clock: Arc, - pub signer: Arc, -} - -impl TestValidator { - /// Create a new TestValidator that signs with the given keypair, operates per the given spec and connects to the - /// supplied beacon node. - /// - /// A `BlockProducer` and `Attester` is created.. - pub fn new( - keypair: Keypair, - beacon_chain: Arc>, - spec: Arc, - ) -> Self { - let slot_clock = Arc::new(TestingSlotClock::new(spec.genesis_slot)); - let signer = Arc::new(TestSigner::new(keypair.clone())); - let beacon_node = Arc::new(DirectBeaconNode::new(beacon_chain.clone())); - let epoch_map = Arc::new(DirectDuties::new(keypair.pk.clone(), beacon_chain.clone())); - - let block_producer = BlockProducer::new( - spec.clone(), - keypair.pk.clone(), - epoch_map.clone(), - slot_clock.clone(), - beacon_node.clone(), - signer.clone(), - ); - - let attester = Attester::new( - epoch_map.clone(), - slot_clock.clone(), - beacon_node.clone(), - signer.clone(), - ); - - Self { - block_producer, - attester, - spec, - epoch_map, - keypair, - beacon_node, - slot_clock, - signer, - } - } - - /// Run the `poll` function on the `BlockProducer` and produce a block. - /// - /// An error is returned if the producer refuses to produce. - pub fn produce_block(&mut self) -> Result { - // Using `DirectBeaconNode`, the validator will always return sucessufully if it tries to - // publish a block. - match self.block_producer.poll() { - Ok(BlockPollOutcome::BlockProduced(_)) => {} - Ok(outcome) => return Err(BlockProduceError::DidNotProduce(outcome)), - Err(error) => return Err(BlockProduceError::PollError(error)), - }; - Ok(self - .beacon_node - .last_published_block() - .expect("Unable to obtain produced block.")) - } - - /// Run the `poll` function on the `Attester` and produce a `FreeAttestation`. - /// - /// An error is returned if the attester refuses to attest. - pub fn produce_free_attestation(&mut self) -> Result { - match self.attester.poll() { - Ok(AttestationPollOutcome::AttestationProduced(_)) => {} - Ok(outcome) => return Err(AttestationProduceError::DidNotProduce(outcome)), - Err(error) => return Err(AttestationProduceError::PollError(error)), - }; - Ok(self - .beacon_node - .last_published_free_attestation() - .expect("Unable to obtain produced attestation.")) - } - - /// Set the validators slot clock to the specified slot. - /// - /// The validators slot clock will always read this value until it is set to something else. - pub fn set_slot(&mut self, slot: u64) { - self.slot_clock.set_slot(slot) - } -} +pub use self::validator::TestValidator; diff --git a/beacon_node/beacon_chain/test_harness/src/validator/validator.rs b/beacon_node/beacon_chain/test_harness/src/validator/validator.rs new file mode 100644 index 000000000..d33a0412b --- /dev/null +++ b/beacon_node/beacon_chain/test_harness/src/validator/validator.rs @@ -0,0 +1,133 @@ +use super::direct_beacon_node::DirectBeaconNode; +use super::direct_duties::DirectDuties; +use super::signer::TestSigner; +use attester::PollOutcome as AttestationPollOutcome; +use attester::{Attester, Error as AttestationPollError}; +use beacon_chain::BeaconChain; +use block_producer::PollOutcome as BlockPollOutcome; +use block_producer::{BlockProducer, Error as BlockPollError}; +use db::MemoryDB; +use slot_clock::TestingSlotClock; +use std::sync::Arc; +use types::{BeaconBlock, ChainSpec, FreeAttestation, Keypair}; + +#[derive(Debug, PartialEq)] +pub enum BlockProduceError { + DidNotProduce(BlockPollOutcome), + PollError(BlockPollError), +} + +#[derive(Debug, PartialEq)] +pub enum AttestationProduceError { + DidNotProduce(AttestationPollOutcome), + PollError(AttestationPollError), +} + +/// A `BlockProducer` and `Attester` which sign using a common keypair. +/// +/// The test validator connects directly to a borrowed `BeaconChain` struct. It is useful for +/// testing that the core proposer and attester logic is functioning. Also for supporting beacon +/// chain tests. +pub struct TestValidator { + pub block_producer: BlockProducer< + TestingSlotClock, + DirectBeaconNode, + DirectDuties, + TestSigner, + >, + pub attester: Attester< + TestingSlotClock, + DirectBeaconNode, + DirectDuties, + TestSigner, + >, + pub spec: Arc, + pub epoch_map: Arc>, + pub keypair: Keypair, + pub beacon_node: Arc>, + pub slot_clock: Arc, + pub signer: Arc, +} + +impl TestValidator { + /// Create a new TestValidator that signs with the given keypair, operates per the given spec and connects to the + /// supplied beacon node. + /// + /// A `BlockProducer` and `Attester` is created.. + pub fn new( + keypair: Keypair, + beacon_chain: Arc>, + spec: Arc, + ) -> Self { + let slot_clock = Arc::new(TestingSlotClock::new(spec.genesis_slot)); + let signer = Arc::new(TestSigner::new(keypair.clone())); + let beacon_node = Arc::new(DirectBeaconNode::new(beacon_chain.clone())); + let epoch_map = Arc::new(DirectDuties::new(keypair.pk.clone(), beacon_chain.clone())); + + let block_producer = BlockProducer::new( + spec.clone(), + keypair.pk.clone(), + epoch_map.clone(), + slot_clock.clone(), + beacon_node.clone(), + signer.clone(), + ); + + let attester = Attester::new( + epoch_map.clone(), + slot_clock.clone(), + beacon_node.clone(), + signer.clone(), + ); + + Self { + block_producer, + attester, + spec, + epoch_map, + keypair, + beacon_node, + slot_clock, + signer, + } + } + + /// Run the `poll` function on the `BlockProducer` and produce a block. + /// + /// An error is returned if the producer refuses to produce. + pub fn produce_block(&mut self) -> Result { + // Using `DirectBeaconNode`, the validator will always return sucessufully if it tries to + // publish a block. + match self.block_producer.poll() { + Ok(BlockPollOutcome::BlockProduced(_)) => {} + Ok(outcome) => return Err(BlockProduceError::DidNotProduce(outcome)), + Err(error) => return Err(BlockProduceError::PollError(error)), + }; + Ok(self + .beacon_node + .last_published_block() + .expect("Unable to obtain produced block.")) + } + + /// Run the `poll` function on the `Attester` and produce a `FreeAttestation`. + /// + /// An error is returned if the attester refuses to attest. + pub fn produce_free_attestation(&mut self) -> Result { + match self.attester.poll() { + Ok(AttestationPollOutcome::AttestationProduced(_)) => {} + Ok(outcome) => return Err(AttestationProduceError::DidNotProduce(outcome)), + Err(error) => return Err(AttestationProduceError::PollError(error)), + }; + Ok(self + .beacon_node + .last_published_free_attestation() + .expect("Unable to obtain produced attestation.")) + } + + /// Set the validators slot clock to the specified slot. + /// + /// The validators slot clock will always read this value until it is set to something else. + pub fn set_slot(&mut self, slot: u64) { + self.slot_clock.set_slot(slot) + } +}