Add progress on test rig

This commit is contained in:
Paul Hauner
2019-01-24 17:05:48 +11:00
parent b29934aed4
commit 6fd3a1a03e
19 changed files with 595 additions and 144 deletions

View File

@@ -0,0 +1,58 @@
use beacon_chain::{block_production::Error as BlockProductionError, BeaconChain};
use block_producer::{BeaconNode as BeaconBlockNode, BeaconNodeError as BeaconBlockNodeError};
use db::ClientDB;
use slot_clock::SlotClock;
use types::{BeaconBlock, PublicKey, Signature};
pub struct DirectBeaconNode<'a, T: ClientDB, U: SlotClock> {
beacon_chain: &'a BeaconChain<T, U>,
}
impl<'a, T: ClientDB, U: SlotClock> DirectBeaconNode<'a, T, U> {
pub fn new(beacon_chain: &'a BeaconChain<T, U>) -> Self {
Self { beacon_chain }
}
}
impl<'a, T: ClientDB, U: SlotClock> BeaconBlockNode for DirectBeaconNode<'a, T, U>
where
BlockProductionError: From<<U>::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(),
))
}
}
/// Returns the value specified by the `set_next_publish_result`.
fn publish_beacon_block(&self, block: BeaconBlock) -> Result<bool, BeaconBlockNodeError> {
Err(BeaconBlockNodeError::DecodeFailure)
}
}

View File

@@ -0,0 +1,37 @@
use beacon_chain::{block_production::Error as BlockProductionError, BeaconChain};
use block_producer::{DutiesReader, DutiesReaderError};
use db::ClientDB;
use slot_clock::SlotClock;
use types::PublicKey;
pub struct DirectDuties<'a, T: ClientDB, U: SlotClock> {
beacon_chain: &'a BeaconChain<T, U>,
pubkey: PublicKey,
}
impl<'a, T: ClientDB, U: SlotClock> DirectDuties<'a, T, U> {
pub fn new(pubkey: PublicKey, beacon_chain: &'a BeaconChain<T, U>) -> Self {
Self {
beacon_chain,
pubkey,
}
}
}
impl<'a, T: ClientDB, U: SlotClock> DutiesReader for DirectDuties<'a, T, U>
where
BlockProductionError: From<<U>::Error>,
{
fn is_block_production_slot(&self, _epoch: u64, 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),
}
}
}

View File

@@ -0,0 +1,9 @@
mod direct_beacon_node;
mod direct_duties;
mod test_rig;
mod validator;
pub use self::direct_beacon_node::DirectBeaconNode;
pub use self::direct_duties::DirectDuties;
pub use self::test_rig::TestRig;
pub use self::validator::TestValidator;

View File

@@ -0,0 +1,85 @@
use super::{DirectBeaconNode, DirectDuties, TestValidator};
use beacon_chain::BeaconChain;
#[cfg(test)]
use block_producer::{test_utils::TestSigner, BlockProducer};
use db::{
stores::{BeaconBlockStore, BeaconStateStore},
MemoryDB,
};
use slot_clock::TestingSlotClock;
use spec::ChainSpec;
use std::sync::{Arc, RwLock};
use types::{Keypair, Validator};
pub struct TestRig<'a> {
db: Arc<MemoryDB>,
beacon_chain: BeaconChain<MemoryDB, TestingSlotClock>,
block_store: Arc<BeaconBlockStore<MemoryDB>>,
state_store: Arc<BeaconStateStore<MemoryDB>>,
validators: Vec<TestValidator<'a>>,
}
impl<'a> TestRig<'a> {
pub fn new(spec: ChainSpec) -> Self {
let db = Arc::new(MemoryDB::open());
let block_store = Arc::new(BeaconBlockStore::new(db.clone()));
let state_store = Arc::new(BeaconStateStore::new(db.clone()));
let slot_clock = TestingSlotClock::new(0);
let mut beacon_chain =
BeaconChain::genesis(state_store.clone(), block_store.clone(), slot_clock, spec)
.unwrap();
/*
let validators = generate_validators(validator_count, &beacon_chain);
beacon_chain.spec = inject_validators_into_spec(beacon_chain.spec.clone(), &validators[..]);
*/
Self {
db,
beacon_chain,
block_store,
state_store,
validators: vec![],
}
}
pub fn generate_validators(&'a mut self, validator_count: usize) {
self.validators = Vec::with_capacity(validator_count);
for _ in 0..validator_count {
self.validators.push(TestValidator::new(&self.beacon_chain));
}
self.beacon_chain.spec =
inject_validators_into_spec(self.beacon_chain.spec.clone(), &self.validators[..]);
}
pub fn process_next_slot(&mut self) {
let slot = self
.beacon_chain
.present_slot()
.expect("Unable to determine slot.")
+ 1;
self.beacon_chain.slot_clock.set_slot(slot);
let block_proposer = self
.beacon_chain
.block_proposer(slot)
.expect("Unable to determine proposer.");
let validator = self
.validators
.get(block_proposer)
.expect("Block proposer unknown");
}
}
fn inject_validators_into_spec(mut spec: ChainSpec, validators: &[TestValidator]) -> ChainSpec {
spec.initial_validators = Vec::with_capacity(validators.len());
spec.initial_balances = Vec::with_capacity(validators.len());
for validator in validators {
spec.initial_validators.push(validator.validator_record());
spec.initial_balances.push(32_000_000_000); // 32 ETH
}
spec
}

View File

@@ -0,0 +1,61 @@
use super::{DirectBeaconNode, DirectDuties};
use beacon_chain::BeaconChain;
#[cfg(test)]
use block_producer::{test_utils::TestSigner, BlockProducer};
use db::MemoryDB;
use slot_clock::TestingSlotClock;
use spec::ChainSpec;
use std::sync::{Arc, RwLock};
use types::{Keypair, Validator};
pub struct TestValidator<'a> {
block_producer: BlockProducer<
TestingSlotClock,
DirectBeaconNode<'a, MemoryDB, TestingSlotClock>,
DirectDuties<'a, MemoryDB, TestingSlotClock>,
TestSigner,
>,
spec: Arc<ChainSpec>,
epoch_map: Arc<DirectDuties<'a, MemoryDB, TestingSlotClock>>,
keypair: Keypair,
beacon_node: Arc<DirectBeaconNode<'a, MemoryDB, TestingSlotClock>>,
slot_clock: Arc<RwLock<TestingSlotClock>>,
signer: Arc<TestSigner>,
}
impl<'a> TestValidator<'a> {
pub fn new(beacon_chain: &'a BeaconChain<MemoryDB, TestingSlotClock>) -> Self {
let spec = Arc::new(ChainSpec::foundation());
let keypair = Keypair::random();
let slot_clock = Arc::new(RwLock::new(TestingSlotClock::new(0)));
let signer = Arc::new(TestSigner::new(keypair.clone()));
let beacon_node = Arc::new(DirectBeaconNode::new(beacon_chain));
let epoch_map = Arc::new(DirectDuties::new(keypair.pk.clone(), beacon_chain));
let block_producer = BlockProducer::new(
spec.clone(),
keypair.pk.clone(),
epoch_map.clone(),
slot_clock.clone(),
beacon_node.clone(),
signer.clone(),
);
Self {
block_producer,
spec,
epoch_map,
keypair,
beacon_node,
slot_clock,
signer,
}
}
pub fn validator_record(&self) -> Validator {
Validator {
pubkey: self.keypair.pk.clone(),
..std::default::Default::default()
}
}
}