Move BeaconChainHarness to interop spec

This commit is contained in:
Paul Hauner 2019-09-04 10:25:30 +10:00
parent 2706025a34
commit 7edc5f37b9
No known key found for this signature in database
GPG Key ID: 303E4494BB28068C
6 changed files with 91 additions and 82 deletions

View File

@ -13,8 +13,8 @@ use std::sync::Arc;
use std::time::SystemTime;
use tree_hash::{SignedRoot, TreeHash};
use types::{
test_utils::generate_deterministic_keypairs, BeaconBlock, BeaconState, ChainSpec, Deposit,
DepositData, Domain, EthSpec, Fork, Hash256, PublicKey, Signature,
BeaconBlock, BeaconState, ChainSpec, Deposit, DepositData, Domain, EthSpec, Fork, Hash256,
Keypair, PublicKey, Signature,
};
enum BuildStrategy<T: BeaconChainTypes> {
@ -33,21 +33,21 @@ pub struct BeaconChainBuilder<T: BeaconChainTypes> {
impl<T: BeaconChainTypes> BeaconChainBuilder<T> {
pub fn recent_genesis(
validator_count: usize,
keypairs: &[Keypair],
minutes: u64,
spec: ChainSpec,
log: Logger,
) -> Result<Self, String> {
Self::quick_start(recent_genesis_time(minutes), validator_count, spec, log)
Self::quick_start(recent_genesis_time(minutes), keypairs, spec, log)
}
pub fn quick_start(
genesis_time: u64,
validator_count: usize,
keypairs: &[Keypair],
spec: ChainSpec,
log: Logger,
) -> Result<Self, String> {
let genesis_state = interop_genesis_state(validator_count, genesis_time, &spec)?;
let genesis_state = interop_genesis_state(keypairs, genesis_time, &spec)?;
Ok(Self::from_genesis_state(genesis_state, spec, log))
}
@ -167,11 +167,10 @@ fn genesis_block<T: EthSpec>(genesis_state: &BeaconState<T>, spec: &ChainSpec) -
/// Reference:
/// https://github.com/ethereum/eth2.0-pm/tree/6e41fcf383ebeb5125938850d8e9b4e9888389b4/interop/mocked_start
fn interop_genesis_state<T: EthSpec>(
validator_count: usize,
keypairs: &[Keypair],
genesis_time: u64,
spec: &ChainSpec,
) -> Result<BeaconState<T>, String> {
let keypairs = generate_deterministic_keypairs(validator_count);
let eth1_block_hash = Hash256::from_slice(&[0x42; 32]);
let eth1_timestamp = 2_u64.pow(40);
let amount = spec.max_effective_balance;
@ -187,7 +186,7 @@ fn interop_genesis_state<T: EthSpec>(
.map(|keypair| {
let mut data = DepositData {
withdrawal_credentials: withdrawal_credentials(&keypair.pk),
pubkey: keypair.pk.into(),
pubkey: keypair.pk.clone().into(),
amount,
signature: Signature::empty_signature().into(),
};
@ -269,7 +268,7 @@ fn recent_genesis_time(minutes: u64) -> u64 {
#[cfg(test)]
mod test {
use super::*;
use types::{EthSpec, MinimalEthSpec};
use types::{test_utils::generate_deterministic_keypairs, EthSpec, MinimalEthSpec};
type TestEthSpec = MinimalEthSpec;
@ -279,7 +278,9 @@ mod test {
let genesis_time = 42;
let spec = &TestEthSpec::default_spec();
let state = interop_genesis_state::<TestEthSpec>(validator_count, genesis_time, spec)
let keypairs = generate_deterministic_keypairs(validator_count);
let state = interop_genesis_state::<TestEthSpec>(&keypairs, genesis_time, spec)
.expect("should build state");
assert_eq!(

View File

@ -34,6 +34,7 @@ pub enum BeaconChainError {
MissingBeaconBlock(Hash256),
MissingBeaconState(Hash256),
SlotProcessingError(SlotProcessingError),
UnableToAdvanceState(String),
NoStateForAttestation {
beacon_block_root: Hash256,
},

View File

@ -1,22 +1,28 @@
use crate::{BeaconChain, BeaconChainTypes, BlockProcessingOutcome, InteropEth1ChainBackend};
use crate::{
AttestationProcessingOutcome, BeaconChain, BeaconChainBuilder, BeaconChainTypes,
BlockProcessingOutcome, InteropEth1ChainBackend,
};
use lmd_ghost::LmdGhost;
use rayon::prelude::*;
use sloggers::{null::NullLoggerBuilder, Build};
use sloggers::{terminal::TerminalLoggerBuilder, types::Severity, Build};
use slot_clock::TestingSlotClock;
use state_processing::per_slot_processing;
use std::marker::PhantomData;
use std::sync::Arc;
use store::MemoryStore;
use store::Store;
use tree_hash::{SignedRoot, TreeHash};
use types::{
test_utils::TestingBeaconStateBuilder, AggregateSignature, Attestation,
AttestationDataAndCustodyBit, BeaconBlock, BeaconState, BitList, ChainSpec, Domain, EthSpec,
Hash256, Keypair, RelativeEpoch, SecretKey, Signature, Slot,
AggregateSignature, Attestation, AttestationDataAndCustodyBit, BeaconBlock, BeaconState,
BitList, ChainSpec, Domain, EthSpec, Hash256, Keypair, RelativeEpoch, SecretKey, Signature,
Slot,
};
pub use types::test_utils::generate_deterministic_keypairs;
pub use crate::persisted_beacon_chain::{PersistedBeaconChain, BEACON_CHAIN_DB_KEY};
pub const HARNESS_GENESIS_TIME: u64 = 1567552690; // 4th September 2019
/// Indicates how the `BeaconChainHarness` should produce blocks.
#[derive(Clone, Copy, Debug)]
pub enum BlockStrategy {
@ -84,46 +90,21 @@ where
E: EthSpec,
{
/// Instantiate a new harness with `validator_count` initial validators.
pub fn new(validator_count: usize) -> Self {
let state_builder = TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(
validator_count,
&E::default_spec(),
);
let (genesis_state, keypairs) = state_builder.build();
Self::from_state_and_keypairs(genesis_state, keypairs)
}
/// Instantiate a new harness with an initial validator for each key supplied.
pub fn from_keypairs(keypairs: Vec<Keypair>) -> Self {
let state_builder = TestingBeaconStateBuilder::from_keypairs(keypairs, &E::default_spec());
let (genesis_state, keypairs) = state_builder.build();
Self::from_state_and_keypairs(genesis_state, keypairs)
}
/// Instantiate a new harness with the given genesis state and a keypair for each of the
/// initial validators in the given state.
pub fn from_state_and_keypairs(genesis_state: BeaconState<E>, keypairs: Vec<Keypair>) -> Self {
pub fn new(keypairs: Vec<Keypair>) -> Self {
let spec = E::default_spec();
let log = TerminalLoggerBuilder::new()
.level(Severity::Warning)
.build()
.expect("logger should build");
let store = Arc::new(MemoryStore::open());
let mut genesis_block = BeaconBlock::empty(&spec);
genesis_block.state_root = Hash256::from_slice(&genesis_state.tree_hash_root());
let builder = NullLoggerBuilder;
let log = builder.build().expect("logger should build");
let chain = BeaconChain::from_genesis(
store,
InteropEth1ChainBackend::default(),
genesis_state,
genesis_block,
spec.clone(),
log,
)
.expect("Terminate if beacon chain generation fails");
let chain =
BeaconChainBuilder::quick_start(HARNESS_GENESIS_TIME, &keypairs, spec.clone(), log)
.unwrap_or_else(|e| panic!("Failed to create beacon chain builder: {}", e))
.build(store.clone(), InteropEth1ChainBackend::default())
.unwrap_or_else(|e| panic!("Failed to build beacon chain: {}", e));
Self {
chain,
@ -163,7 +144,10 @@ where
BlockStrategy::ForkCanonicalChainAt { previous_slot, .. } => previous_slot,
};
self.get_state_at_slot(state_slot)
self.chain
.state_at_slot(state_slot)
.expect("should find state for slot")
.clone()
};
// Determine the first slot where a block should be built.
@ -201,21 +185,6 @@ where
head_block_root.expect("did not produce any blocks")
}
fn get_state_at_slot(&self, state_slot: Slot) -> BeaconState<E> {
let state_root = self
.chain
.rev_iter_state_roots()
.find(|(_hash, slot)| *slot == state_slot)
.map(|(hash, _slot)| hash)
.expect("could not find state root");
self.chain
.store
.get(&state_root)
.expect("should read db")
.expect("should find state root")
}
/// Returns a newly created block, signed by the proposer for the given slot.
fn build_block(
&self,
@ -289,9 +258,14 @@ where
)
.into_iter()
.for_each(|attestation| {
self.chain
match self
.chain
.process_attestation(attestation)
.expect("should process attestation");
.expect("should not error during attestation processing")
{
AttestationProcessingOutcome::Processed => (),
other => panic!("did not successfully process attestation: {:?}", other),
}
});
}

View File

@ -3,11 +3,14 @@
#[macro_use]
extern crate lazy_static;
use beacon_chain::test_utils::{
use beacon_chain::AttestationProcessingOutcome;
use beacon_chain::{
test_utils::{
AttestationStrategy, BeaconChainHarness, BlockStrategy, CommonTypes, PersistedBeaconChain,
BEACON_CHAIN_DB_KEY,
},
BlockProcessingOutcome,
};
use beacon_chain::AttestationProcessingOutcome;
use lmd_ghost::ThreadSafeReducedTree;
use rand::Rng;
use store::{MemoryStore, Store};
@ -25,7 +28,7 @@ lazy_static! {
type TestForkChoice = ThreadSafeReducedTree<MemoryStore, MinimalEthSpec>;
fn get_harness(validator_count: usize) -> BeaconChainHarness<TestForkChoice, MinimalEthSpec> {
let harness = BeaconChainHarness::from_keypairs(KEYPAIRS[0..validator_count].to_vec());
let harness = BeaconChainHarness::new(KEYPAIRS[0..validator_count].to_vec());
harness.advance_slot();
@ -461,3 +464,32 @@ fn free_attestations_added_to_fork_choice_all_updated() {
}
}
}
#[test]
fn produces_and_processes_with_genesis_skip_slots() {
let num_validators = 8;
let harness_a = get_harness(num_validators);
let harness_b = get_harness(num_validators);
let skip_slots = 9;
for _ in 0..skip_slots {
harness_a.advance_slot();
harness_b.advance_slot();
}
harness_a.extend_chain(
1,
BlockStrategy::OnCanonicalHead,
// No attestation required for test.
AttestationStrategy::SomeValidators(vec![]),
);
assert_eq!(
harness_b
.chain
.process_block(harness_a.chain.head().beacon_block.clone()),
Ok(BlockProcessingOutcome::Processed {
block_root: harness_a.chain.head().beacon_block_root
})
);
}

View File

@ -6,8 +6,8 @@ pub mod error;
pub mod notifier;
use beacon_chain::{
lmd_ghost::ThreadSafeReducedTree, slot_clock::SystemTimeSlotClock, store::Store, BeaconChain,
BeaconChainBuilder,
lmd_ghost::ThreadSafeReducedTree, slot_clock::SystemTimeSlotClock, store::Store,
test_utils::generate_deterministic_keypairs, BeaconChain, BeaconChainBuilder,
};
use exit_future::Signal;
use futures::{future::Future, Stream};
@ -106,7 +106,7 @@ where
"method" => "recent"
);
BeaconChainBuilder::recent_genesis(
*validator_count,
&generate_deterministic_keypairs(*validator_count),
*minutes,
spec.clone(),
log.clone(),
@ -125,7 +125,7 @@ where
);
BeaconChainBuilder::quick_start(
*genesis_time,
*validator_count,
&generate_deterministic_keypairs(*validator_count),
spec.clone(),
log.clone(),
)?

View File

@ -4,7 +4,8 @@
extern crate lazy_static;
use beacon_chain::test_utils::{
AttestationStrategy, BeaconChainHarness as BaseBeaconChainHarness, BlockStrategy,
generate_deterministic_keypairs, AttestationStrategy,
BeaconChainHarness as BaseBeaconChainHarness, BlockStrategy,
};
use lmd_ghost::{LmdGhost, ThreadSafeReducedTree as BaseThreadSafeReducedTree};
use rand::{prelude::*, rngs::StdRng};
@ -51,7 +52,7 @@ struct ForkedHarness {
impl ForkedHarness {
/// A new standard instance of with constant parameters.
pub fn new() -> Self {
let harness = BeaconChainHarness::new(VALIDATOR_COUNT);
let harness = BeaconChainHarness::new(generate_deterministic_keypairs(VALIDATOR_COUNT));
// Move past the zero slot.
harness.advance_slot();