Add new beacon chain test harness
This commit is contained in:
parent
1128de535d
commit
8fb6ffffe2
@ -88,6 +88,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
genesis_block: BeaconBlock,
|
genesis_block: BeaconBlock,
|
||||||
spec: ChainSpec,
|
spec: ChainSpec,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
|
genesis_state.build_all_caches(&spec)?;
|
||||||
|
|
||||||
let state_root = genesis_state.canonical_root();
|
let state_root = genesis_state.canonical_root();
|
||||||
store.put(&state_root, &genesis_state)?;
|
store.put(&state_root, &genesis_state)?;
|
||||||
|
|
||||||
@ -105,8 +107,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
state_root,
|
state_root,
|
||||||
));
|
));
|
||||||
|
|
||||||
genesis_state.build_all_caches(&spec)?;
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
spec,
|
spec,
|
||||||
slot_clock,
|
slot_clock,
|
||||||
|
@ -5,6 +5,7 @@ mod fork_choice;
|
|||||||
pub mod iter;
|
pub mod iter;
|
||||||
mod metrics;
|
mod metrics;
|
||||||
mod persisted_beacon_chain;
|
mod persisted_beacon_chain;
|
||||||
|
mod test_utils;
|
||||||
|
|
||||||
pub use self::beacon_chain::{BeaconChain, BeaconChainTypes, BlockProcessingOutcome};
|
pub use self::beacon_chain::{BeaconChain, BeaconChainTypes, BlockProcessingOutcome};
|
||||||
pub use self::checkpoint::CheckPoint;
|
pub use self::checkpoint::CheckPoint;
|
||||||
|
147
beacon_node/beacon_chain/src/test_utils.rs
Normal file
147
beacon_node/beacon_chain/src/test_utils.rs
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
use crate::{BeaconChain, BeaconChainTypes, BlockProcessingOutcome};
|
||||||
|
use lmd_ghost::{LmdGhost, ThreadSafeReducedTree};
|
||||||
|
use slot_clock::SlotClock;
|
||||||
|
use slot_clock::TestingSlotClock;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use store::MemoryStore;
|
||||||
|
use tree_hash::{SignedRoot, TreeHash};
|
||||||
|
use types::{
|
||||||
|
test_utils::TestingBeaconStateBuilder, BeaconBlock, ChainSpec, Domain, EthSpec, Hash256,
|
||||||
|
Keypair, MinimalEthSpec, Signature,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct CommonTypes<L, E>
|
||||||
|
where
|
||||||
|
L: LmdGhost<MemoryStore, E>,
|
||||||
|
E: EthSpec,
|
||||||
|
{
|
||||||
|
_phantom_l: PhantomData<L>,
|
||||||
|
_phantom_e: PhantomData<E>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<L, E> BeaconChainTypes for CommonTypes<L, E>
|
||||||
|
where
|
||||||
|
L: LmdGhost<MemoryStore, E>,
|
||||||
|
E: EthSpec,
|
||||||
|
{
|
||||||
|
type Store = MemoryStore;
|
||||||
|
type SlotClock = TestingSlotClock;
|
||||||
|
type LmdGhost = L;
|
||||||
|
type EthSpec = E;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BeaconChainHarness<L, E>
|
||||||
|
where
|
||||||
|
L: LmdGhost<MemoryStore, E>,
|
||||||
|
E: EthSpec,
|
||||||
|
{
|
||||||
|
chain: BeaconChain<CommonTypes<L, E>>,
|
||||||
|
keypairs: Vec<Keypair>,
|
||||||
|
spec: ChainSpec,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<L, E> BeaconChainHarness<L, E>
|
||||||
|
where
|
||||||
|
L: LmdGhost<MemoryStore, E>,
|
||||||
|
E: EthSpec,
|
||||||
|
{
|
||||||
|
pub fn new(validator_count: usize) -> Self {
|
||||||
|
let spec = E::default_spec();
|
||||||
|
|
||||||
|
let store = Arc::new(MemoryStore::open());
|
||||||
|
|
||||||
|
let state_builder =
|
||||||
|
TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(validator_count, &spec);
|
||||||
|
let (genesis_state, keypairs) = state_builder.build();
|
||||||
|
|
||||||
|
let mut genesis_block = BeaconBlock::empty(&spec);
|
||||||
|
genesis_block.state_root = Hash256::from_slice(&genesis_state.tree_hash_root());
|
||||||
|
|
||||||
|
// Slot clock
|
||||||
|
let slot_clock = TestingSlotClock::new(
|
||||||
|
spec.genesis_slot,
|
||||||
|
genesis_state.genesis_time,
|
||||||
|
spec.seconds_per_slot,
|
||||||
|
);
|
||||||
|
|
||||||
|
let chain = BeaconChain::from_genesis(
|
||||||
|
store,
|
||||||
|
slot_clock,
|
||||||
|
genesis_state,
|
||||||
|
genesis_block,
|
||||||
|
spec.clone(),
|
||||||
|
)
|
||||||
|
.expect("Terminate if beacon chain generation fails");
|
||||||
|
|
||||||
|
Self {
|
||||||
|
chain,
|
||||||
|
keypairs,
|
||||||
|
spec,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extend_canonical_chain(&self) {
|
||||||
|
self.chain.slot_clock.advance_slot();
|
||||||
|
self.chain.catchup_state().expect("should catchup state");
|
||||||
|
|
||||||
|
let block = self.build_block();
|
||||||
|
let outcome = self
|
||||||
|
.chain
|
||||||
|
.process_block(block)
|
||||||
|
.expect("should process block");
|
||||||
|
assert_eq!(outcome, BlockProcessingOutcome::Processed);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_block(&self) -> BeaconBlock {
|
||||||
|
let slot = self.chain.read_slot_clock().unwrap();
|
||||||
|
|
||||||
|
let sk = {
|
||||||
|
let proposer = self
|
||||||
|
.chain
|
||||||
|
.block_proposer(slot)
|
||||||
|
.expect("should get block propoer");
|
||||||
|
&self.keypairs[proposer].sk
|
||||||
|
};
|
||||||
|
|
||||||
|
let fork = &self.chain.head().beacon_state.fork;
|
||||||
|
|
||||||
|
let randao_reveal = {
|
||||||
|
let epoch = slot.epoch(E::slots_per_epoch());
|
||||||
|
let message = epoch.tree_hash_root();
|
||||||
|
let domain = self.spec.get_domain(epoch, Domain::Randao, fork);
|
||||||
|
Signature::new(&message, domain, sk)
|
||||||
|
};
|
||||||
|
|
||||||
|
let (mut block, _state) = self
|
||||||
|
.chain
|
||||||
|
.produce_block(randao_reveal)
|
||||||
|
.expect("should producer block");
|
||||||
|
|
||||||
|
block.signature = {
|
||||||
|
let message = block.signed_root();
|
||||||
|
let epoch = block.slot.epoch(E::slots_per_epoch());
|
||||||
|
let domain = self.spec.get_domain(epoch, Domain::BeaconProposer, fork);
|
||||||
|
Signature::new(&message, domain, sk)
|
||||||
|
};
|
||||||
|
|
||||||
|
block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub const VALIDATOR_COUNT: usize = 16;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn build_on_genesis() {
|
||||||
|
let harness: BeaconChainHarness<
|
||||||
|
ThreadSafeReducedTree<MemoryStore, MinimalEthSpec>,
|
||||||
|
MinimalEthSpec,
|
||||||
|
> = BeaconChainHarness::new(VALIDATOR_COUNT);
|
||||||
|
|
||||||
|
harness.extend_canonical_chain();
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,10 @@ impl TestingSlotClock {
|
|||||||
pub fn set_slot(&self, slot: u64) {
|
pub fn set_slot(&self, slot: u64) {
|
||||||
*self.slot.write().expect("TestingSlotClock poisoned.") = Slot::from(slot);
|
*self.slot.write().expect("TestingSlotClock poisoned.") = Slot::from(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn advance_slot(&self) {
|
||||||
|
self.set_slot(self.present_slot().unwrap().unwrap().as_u64() + 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SlotClock for TestingSlotClock {
|
impl SlotClock for TestingSlotClock {
|
||||||
|
Loading…
Reference in New Issue
Block a user